Tightly Coupling pallet error: ambiguous associated type `Currency` in bounds of `T` - substrate

I have following config file, I added schelling game pallet as tightly coupling pallet:
use frame_support::{
traits::{Currency, ExistenceRequirement, Get, ReservableCurrency, WithdrawReasons},
};
#[pallet::config]
pub trait Config: frame_system::Config + schelling_game::Config{
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
type Currency: ReservableCurrency<Self::AccountId>;
type RandomnessSource: Randomness<Self::Hash, Self::BlockNumber>;
}
I have following code in the function:
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(2,2))]
pub fn add_profile_fund(origin: OriginFor<T>, citizenid: u128) -> DispatchResult {
let who = ensure_signed(origin)?;
let deposit = <RegistrationFee<T>>::get();
let imb = T::Currency::withdraw(
&who,
deposit,
WithdrawReasons::TRANSFER,
ExistenceRequirement::AllowDeath,
)?;
It gives error:
ambiguous associated type Currency in bounds of T
ambiguous associated type Currency
note: associated type T could derive from schelling_game::Config
help: use fully qualified syntax to disambiguate: <T as pallet::Config>::Currency
When I add
let imb = <T as frame_system::Config>::Currency::withdraw()
It gives error:
cannot find associated type Currency in trait frame_system::Config
not found in frame_system::Config
Edit:
The error is because I have used currency trait in both the pallet. How can I use currency trait in both pallets?

I think the error/warning message has given you the answer you need 🙂 . Could you try:
let imb = <T as pallet::Config>::Currency::withdraw();
and see if this works?
What I am not sure how is Currency ambiguous, as the associated type is only defined in your pallet and not in System Pallet? But well, if the compiler tells us to do so, let's not argue with it for now.
Update:
oh, I think the pallet module exports the Config trait out and the trait is now accessible as schelling_game::Config also as mentioned in the error message. So there are two names now - pallet::Config and schelling_game::Config and rust compiler treats them as ambiguous, but they are the same thing really.

Related

What are the macros #[pallet::genesis_config] and #[pallet::genesis_build] doing on the sudo pallet?

#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
/// The `AccountId` of the sudo key.
pub key: T::AccountId,
}
#[cfg(feature = "std")]
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { key: Default::default() }
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
<Key<T>>::put(&self.key);
}
}
What is happening here with genesis_config and genesis_build macros here? Some reading seemed to suggest that implement the trait GenesisBuild<T,I = ()> but I am confused as the docs read: "T and I are placeholder for pallet trait and pallet instance."
What are pallet instances? I also assume pallet trait means the Config trait for the sudo pallet. Is it some how related to configuring a unique StorageValue for the Genesis block so that each instance of a running node can verify that the same Account is Root? Can someone help break it down for me.
What are pallet instances?
Pallets can be made instantiable. This means a Pallet can be used multiple times in a runtime. Each instance will use the same code (modulo different configuration through the configuration trait), but the storage will be different for each instance.
See: https://docs.substrate.io/how-to-guides/v3/basics/instantiable-pallets/
I also assume pallet trait means the Config trait for the sudo pallet. Is it some how related to configuring a unique StorageValue for the Genesis block so that each instance of a running node can verify that the same Account is Root? Can someone help break it down for me.
Yes Pallet trait means the Config trait.
The point here with GenesisBuild taking two generic arguments is to support all kinds of Pallets. Every Pallet is configurable through the trait, so the GenesisBuild trait needs to take the Config generic parameter T. Some Pallets can be instantiable, so it also needs to take I.
This all boils down to some Rust "quirks" to support instantiable Pallets that are using the default instance and custom instances and also to support Pallets that don't use any instancing at all.
#[pallet::genesis_build] implements the trait sp_runtime::BuildModuleGenesisStorage which puts the initial state into the pallet's storage at genesis time.
(The pallet can put state into child storage also at that point.)
The pub enum/struct with #[pallet::genesis_config] holds the fields that genesis_build reads in order to set up the storage. For example there may be investors at genesis that need a vesting schedule set up (See the vesting pallet: https://github.com/paritytech/substrate/blob/3cdb30e1ecbafe8a866317d4550c921b4d686869/frame/vesting/src/lib.rs#L231 ). So for the sudo pallet, the genesis_config struct holds the root key which is set here:
GenesisConfig {
sudo: SudoConfig {
// Assign network admin rights.
key: root_key,
},
...
}
( https://github.com/paritytech/substrate/blob/3cdb30e1ecbafe8a866317d4550c921b4d686869/bin/node-template/node/src/chain_spec.rs#L150 )
Docs for genesis_config are here: https://docs.substrate.io/rustdocs/latest/frame_support/attr.pallet.html#genesis-config-palletgenesis_config-optional

Unknown types found, no types for DepartmentDetails

I am trying to use struct in substrate
#[derive(PartialEq, Eq, PartialOrd, Ord, Default, Clone, Encode, Decode, RuntimeDebug)]
pub struct DepartmentDetails {
pub name: Vec<u8>,
pub location: Vec<u8>,
pub details: Vec<u8>,
pub departmentid: u128,
}
In decl_stroage
Department get(fn department_name): map hasher(blake2_128_concat) u128 => DepartmentDetails;
Though node runs successfully without error, it give error with polkadotjs app, saying:
Unknown types found, no types for DepartmentDetails
https://substrate.dev/recipes/structs.html
Polkadot-js can only construct and display types that it understands.
See the FAQ here.
For development you can add custom type descriptions in the Settings > Developer tab.
For production you can add type descriptions to your polkadot-js based UI via extending the types as described here.

What is the difference between method call syntax `foo.method()` and UFCS `Foo::method(&foo)`?

Is there any difference in Rust between calling a method on a value, like this:
struct A { e: u32 }
impl A {
fn show(&self) {
println!("{}", self.e)
}
}
fn main() {
A { e: 0 }.show();
}
...and calling it on the type, like this:
fn main() {
A::show(&A { e: 0 })
}
Summary: The most important difference is that the universal function call syntax (UFCS) is more explicit than the method call syntax.
With UFCS there is basically no ambiguity what function you want to call (there is still a longer form of the UFCS for trait methods, but let's ignore that for now). The method call syntax, on the other hand, requires more work in the compiler to figure out which method to call and how to call it. This manifests in mostly two things:
Method resolution: figure out if the method is inherent (bound to the type, not a trait) or a trait method. And in the latter case, also figure out which trait it belongs to.
Figure out the correct receiver type (self) and potentially use type coercions to make the call work.
Receiver type coercions
Let's take a look at this example to understand the type coercions to the receiver type:
struct Foo;
impl Foo {
fn on_ref(&self) {}
fn on_mut_ref(&mut self) {}
fn on_value(self) {}
}
fn main() {
let reference = &Foo; // type `&Foo`
let mut_ref = &mut Foo; // type `&mut Foo`
let mut value = Foo; // type `Foo`
// ...
}
So we have three methods that take Foo, &Foo and &mut Foo receiver and we have three variables with those types. Let's try out all 9 combinations with each, method call syntax and UFCS.
UFCS
Foo::on_ref(reference);
//Foo::on_mut_ref(reference); error: mismatched types
//Foo::on_value(reference); error: mismatched types
//Foo::on_ref(mut_ref); error: mismatched types
Foo::on_mut_ref(mut_ref);
//Foo::on_value(mut_ref); error: mismatched types
//Foo::on_ref(value); error: mismatched types
//Foo::on_mut_ref(value); error: mismatched types
Foo::on_value(value);
As we can see, only the calls succeed where the types are correct. To make the other calls work we would have to manually add & or &mut or * in front of the argument. That's the standard behavior for all function arguments.
Method call syntax
reference.on_ref();
//reference.on_mut_ref(); error: cannot borrow `*reference` as mutable
//reference.on_value(); error: cannot move out of `*reference`
mut_ref.on_ref();
mut_ref.on_mut_ref();
//mut_ref.on_value(); error: cannot move out of `*mut_ref`
value.on_ref();
value.on_mut_ref();
value.on_value();
Only three of the method calls lead to an error while the others succeed. Here, the compiler automatically inserts deref (dereferencing) or autoref (adding a reference) coercions to make the call work. Also note that the three errors are not "type mismatch" errors: the compiler already tried to adjust the type correctly, but this lead to other errors.
There are some additional coercions:
Unsize coercions, described by the Unsize trait. Allows you to call slice methods on arrays and to coerce types into trait objects of traits they implement.
Advanced deref coercions via the Deref trait. This allows you to call slice methods on Vec, for example.
Method resolution: figuring out what method to call
When writing lhs.method_name(), then the method method_name could be an inherent method of the type of lhs or it could belong to a trait that's in scope (imported). The compiler has to figure out which one to call and has a number of rules for this. When getting into the details, these rules are actually really complex and can lead to some surprising behavior. Luckily, most programmers will never have to deal with that and it "just works" most of the time.
To give a coarse overview how it works, the compiler tries the following things in order, using the first method that is found.
Is there an inherent method with the name method_name where the receiver type fits exactly (does not need coercions)?
Is there a trait method with the name method_name where the receiver type fits exactly (does not need coercions)?
Is there an inherent method with the name method_name? (type coercions will be performed)
Is there a trait method with the name method_name? (type coercions will be performed)
(Again, note that this is still a simplification. Different type of coercions are preferred over others, for example.)
This shows one rule that most programmers know: inherent methods have a higher priority than trait methods. But a bit unknown is the fact that whether or not the receiver type fits perfectly is a more important factor. There is a quiz that nicely demonstrates this: Rust Quiz #23. More details on the exact method resolution algorithm can be found in this StackOverflow answer.
This set of rules can actually make a bunch of changes to an API to be breaking changes. We currently have to deal with that in the attempt to add an IntoIterator impl for arrays.
Another – minor and probably very obvious – difference is that for the method call syntax, the type name does not have to be imported.
Apart from that it's worth pointing out what is not different about the two syntaxes:
Runtime behavior: no difference whatsoever.
Performance: the method call syntax is "converted" (desugared) into basically the UFCS pretty early inside the compiler, meaning that there aren't any performance differences either.

How do I constrain associated types on a non-owned trait? [duplicate]

I have this code:
extern crate serde;
use serde::de::DeserializeOwned;
use serde::Serialize;
trait Bar<'a, T: 'a>
where
T: Serialize,
&'a T: DeserializeOwned,
{
}
I would like to write this using an associated type, because the type T is unimportant to the users of this type. I got this far:
trait Bar {
type T: Serialize;
}
I cannot figure out how to specify the other bound.
Ultimately, I want to use a function like this:
extern crate serde_json;
fn test<I: Bar>(t: I::T) -> String {
serde_json::to_string(&t).unwrap()
}
The "correct" solution is to place the bounds on the trait, but referencing the associated type. In this case, you can also use higher ranked trait bounds to handle the reference:
trait Bar
where
Self::T: Serialize,
// ^^^^^^^ Bounds on an associated type
for<'a> &'a Self::T: DeserializeOwned,
// ^^^^^^^^^^^ Higher-ranked trait bounds
{
type T;
}
However, this doesn't work yet.
I believe that you will need to either:
wait for issue 20671 and/or issue 50346 to be fixed.
wait for the generic associated types feature which introduces where clauses on associated types.
In the meantime, the workaround is to duplicate the bound everywhere it's needed:
fn test<I: Bar>(t: I::T) -> String
where
for<'a> &'a I::T: DeserializeOwned,
{
serde_json::to_string(&t).unwrap()
}

What does the 'where' clause within a trait do?

If I have this code:
trait Trait {
fn f(&self) -> i32 where Self: Sized;
fn g(&self) -> i32;
}
fn object_safety_dynamic(x: &Trait) {
x.f(); // error
x.g(); // works
}
What does the where clause actually do?
Naively, I was thinking where Self: Sized; dictates something about the type implementing Trait, like 'if you implement Trait for type A your type A must be sized, i.e., it can be i32 but not [i32].
However, such a constraint would rather go as trait Trait: Sized (correct me if I am wrong)?
Now I noticed where Self: Sized; actually determines if I can call f or g from within object_safety_dynamic.
My questions:
What happens here behind the scenes?
What (in simple English) am I actually telling the compiler by where Self: Sized; that makes g() work but f() not?
In particular: Since &self is a reference anyway, what compiled difference exists between f and g for various (sized or unsized) types. Wouldn't it always boil down to something like _vtable_f_or_g(*self) -> i32, regardless of where or if the type is sized or not?
Why can I implement Trait for both u8 and [u8]. Shouldn't the compiler actually stop me from implementing f() for [u8], instead of throwing an error at the call site?
fn f(&self) -> i32 where Self: Sized;
This says that f is only defined for types that also implement Sized. Unsized types may still implement Trait, but f will not be available.
Inside object_safety_dynamic, calling x.f() is actually doing: (*x).f(). While x is sized because it's a pointer, *x might not be because it could be any implementation of Trait. But code inside the function has to work for any valid argument, so you are not allowed to call x.f() there.
What does the where clause actually do?
Naively, I was thinking where Self: Sized; dictates something about the type implementing Trait, like 'if you implement Trait for type A your type A must be sized, i.e., it can be i32 but not [i32].
However, such a constraint would rather go as trait Trait: Sized
This is correct.
However, in this case, the bound applies only to the function. where bounds on functions are only checked at the callsite.
What happens here behind the scenes?
There is a confusing bit about rust's syntax which is that Trait can refer to either
The trait Trait; or
The "trait object" Trait, which is actually a type, not an object.
Sized is a trait, and any type T that is Sized may have its size taken as a constant, by std::mem::size_of::<T>(). Such types that are not sized are str and [u8], whose contents do not have a fixed size.
The type Trait is also unsized. Intuitively, this is because Trait as a type consists of all values of types that implement the trait Trait, which may have varying size. This means you can never have a value of type Trait - you can only refer to one via a "fat pointer" such as &Trait or Box<Trait> and so on. These have the size of 2 pointers - one for a vtable, one for the data. It looks roughly like this:
struct &Trait {
pub data: *mut (),
pub vtable: *mut (),
}
There is automatically an impl of the form:
impl Trait /* the trait */ for Trait /* the type */ {
fn f(&self) -> i32 where Self: Sized { .. }
fn g(&self) -> i32 {
/* vtable magic: something like (self.vtable.g)(self.data) */
}
}
What (in simple English) am I actually telling the compiler by where Self: Sized; that makes g() work but f() not?
Note that since, as I mentioned, Trait is not Sized, the bound Self: Sized is not satisfied and so the function f cannot be called where Self == Trait.
In particular: Since &self is a reference anyway, what compiled difference exists between f and g for various (sized or unsized) types. Wouldn't it always boil down to something like _vtable_f_or_g(*self) -> i32, regardless of where or if the type is sized or not?
The type Trait is always unsized. It doesn't matter which type has been coerced to Trait. The way you call the function with a Sized variable is to use it directly:
fn generic<T: Trait + Sized>(x: &T) { // the `Sized` bound is implicit, added here for clarity
x.f(); // compiles just fine
x.g();
}
Why can I implement Trait for both u8 and [u8]. Shouldn't the compiler actually stop me from implementing f() for [u8], instead of throwing an error at the call site?
Because the trait is not bounded by Self: Sized - the function f is. So there is nothing stopping you from implementing the function - it's just that the bounds on the function can never be satisfied, so you can never call it.

Resources