-
Notifications
You must be signed in to change notification settings - Fork 2.6k
add frame_system::DefaultConfig
to individual pallet DefaultConfigs
#14453
Conversation
frame_system::DefaultConfig
to individual pallet DefaultConfigs
Not sure why you not try out what I had outlined here: #13454 (comment) This should also give you access to the types from |
I had actually overlooked it, thanks for the follow-up. I will look into it and revise. |
@bkchr the only issue I see with your approach is what I have highlighted here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=34052108e3149aedb7f80e367eac85c7
I will probably try Solution 2 for now, but it is note worthy that this will become a mishmash as soon as you start bounding UPDATE: I am not quite sure if 2 works given that we can have some type alias like |
@kianenigma the link doesn't work. |
If I understand this correctly, it sounds like the correct solution. Basically you are saying, if we see that |
@bkchr I was looking into your suggestion, specially around: trait DefaultSomethingConfig<T: SomethingConfig> {
type DoSomething: DoSomething<T::AccountId>;
type Whatever;
} However, we would need the generic to be bound by trait DefaultSystemConfig {
type AccountId = u64;
}
trait DefaultSomethingConfig<T: DefaultSystemConfig> {
type DoSomething: DoSomething<T::AccountId>;
type Whatever;
} Thus, we would need a separate expansion for CC: @kianenigma @sam0x17 |
Not suer why this is the case? Ideally, we want the Perhaps it would be useful to clean up the rust-playground link with some better names (I find this |
@kianenigma Please take a look at this one: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=09bd639ef9fa8e32f8bb552273517c2e |
Question is, how often do we see this? But this is the proper solution using Rust. |
IMO, this would actually happen for all types that are referenced in the super trait and the current trait. The reason being that the type in the actual config would be different than DefaultConfig. However, we are specifying the generic bound as the config (and not DefaultConfig), causing the conflict. |
That was not my question. My question was on how many types we have where this is required. For sure for stuff like |
I can think of AccountId, AssetId and AssetBalance. Probably a few others as well? |
Yeah for sure, but what would be the other way to solve this? |
bot fmt |
@gupnik https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/3181922 was started for your command Comment |
@gupnik Command |
…ate into kiz-derive-impl-system
@bkchr @kianenigma @sam0x17 This is ready for review. |
Another point this pr is missing is when a pallet has not only the system pallet as supertrait, but also another pallet. So, we should be generic over the supertraits. |
With the way this PR is working, there seems to be no path to have defaults for things like |
I was hoping to pick up this suggestion from @sam0x17 as a follow-up - #14437 (comment) |
I don't think that this will work all the way though, even with // frame-system
trait DefaultConfig {
type Block: Bound1 + Bound2 + ...
type RuntimeEvent; // no bound, because we marked it as such.
} But then what? still, somewhere, in // still in frame-system
impl frame_system::DefaultConfig for PoorTypeThatCannotStillProvideADefaultForRuntimeEvent {
type RuntimeEvent = ???
} Which as I joked in the name, still cannot provide a sensible default for The only solution to fix this, as far as I can see, is to make something be generic over |
Thanks, I do see your point but I am not completely sure if this approach would work as well. Even if trait DefaultConfig<T: frame_system::Config> {
type RuntimeEvent;
} this would still require someone to specify RuntimeEvent at the impl site? My idea with trait DefaultConfig {
type RuntimeEvent; // no bound, because we marked it as such.
}
struct TestDefaultConfig;
impl DefaultConfig for TestDefaultConfig {
#[verbatim] // add an attribute here to hint derive_impl
type RuntimeEvent = ();
} and later impl frame_system::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
} Note that This struct TestDefaultConfig;
impl DefaultConfig for TestDefaultConfig {
#[verbatim(TestBlock)]
type Block = ();
} becomes impl frame_system::Config for Runtime {
type Block = TestBlock;
} and assumes that TestBlock exists. I still need to see this in actual code to make sure that it works, but just wanted to put it down here to see if this makes sense at all. |
I am actually writing the docs right now for |
#14682 describes the POC for this idea. @kianenigma @bkchr @sam0x17 Would love to get some feedback on it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks reasonable to me. I think this should migrate over painlessly to supertrait
, which I'm planning to release on crates.io tonight and should handle some of these edge cases, especially around generics, more gracefully
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't approve this myself, but I had another look and happy to see this merged :)
I'm not yet clear on what issue we exactly solve with To me it seems like with a combination of this and #14682 we will get all the features that we want. |
bot merge |
step in paritytech/polkadot-sdk#171. It solves the issue explained in the next section, and it makes
pallet-proxy
andpallet-multisig
usederive_impl
forframe-system
andpallet-balances
.Overview
This changes the
DeriveImpl
experimental line of work as follows. Before this PR, the generated trait always looked like this:After this PR, if the
trait Config
is itself bound byframe_system::Config
, then it generates the following:This requires you to implement for
frame_system::DefaultConfig
eg.TestDefaultConfig
, but luckily this can in itself be done byderive_impl
. For example, inpallet-example-default-config
, we have:This allows types that are reliant on
frame_system::Config
to also possibly have defaults, as long as they are present inframe_system::DefaultConfig
.Something like
type Foo: Get<<Self as frame_system::Config>::RuntimeCall>
still can (and for the foreseeable future will) not have a default, as it is not present inframe_system::DefaultConfig
.Next Steps / Questions
Currently, the code for
impl DefaultConfig for SomeStruct
is pure Rust. So, we don't have any way to injectimpl frame_system::DefaultConfig for TestDefaultConfig {}
into it. For now, I am happy to keep it as is, but possibly prior to stabilization, we can have something like#[pallet::default_config_impl] struct TestDefaultConfig
and this should:register_default_impl
impl frame_system::DefaultConfig for _
Moreover, the current implementation indeed relies on the name
frame_system::DefaultConfig
, which is fine for now.