Metadata V16 (unstable): Enrich metadata with associated types of config traits #5274
Metadata V16 (unstable): Enrich metadata with associated types of config traits #5274
Conversation
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
types Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
|
@bkchr could you please have a quick look whenever you have some time? 🙏 Thanks everyone for the reviews here 🙏 |
| if !contains_type_info_bound(ty) { | ||
| let msg = format!( | ||
| "Invalid #[pallet::include_metadata] in #[pallet::config], collected type `{}` \ | ||
| does not implement `scale::TypeInfo`", |
There was a problem hiding this comment.
nitpick, maybe we can say: does not explicitly bound TypeInfo or Parameter.
| ty.bounds.iter().any(|bound| { | ||
| let syn::TypeParamBound::Trait(bound) = bound else { return false }; | ||
|
|
||
| KNOWN_TYPE_INFO_BOUNDS.iter().any(|known| bound.path.is_ident(known)) |
There was a problem hiding this comment.
I think that this will not match scale::TypeInfo but only TypeInfo, isn't it?
What I mean is that we do the match on the whole path, not the last segment, no?
If we want to support only this. Then we can say in the error message of include_metadata something like: "Note: only ident is supported, e.g. scale::TypeInfo is not detected, only TypeInfo.
There was a problem hiding this comment.
We should just take the last element of the path to improve the detection?
bkchr
left a comment
There was a problem hiding this comment.
Mainly left some nitpicks. Generally looking good. Good work 👍
| } | ||
|
|
||
| if let syn::TraitItem::Type(ref ty) = trait_item { | ||
| if !contains_type_info_bound(ty) { |
There was a problem hiding this comment.
Could we implement here a mix of:
https://docs.rs/static_assertions/1.1.0/src/static_assertions/assert_impl.rs.html#329-356
and
This should give some very nice error message.
There was a problem hiding this comment.
Ahh but maybe not possible. Not sure, but worth a try.
| // | ||
| // They must provide a type item that implements `TypeInfo`. | ||
| (PalletAttrType::IncludeMetadata(_), syn::TraitItem::Type(ref typ)) => { | ||
| already_collected_associated_type = Some(pallet_attr._bracket.span.join()); |
There was a problem hiding this comment.
There should be an error if the attribute is passed multiple times.
| ty.bounds.iter().any(|bound| { | ||
| let syn::TypeParamBound::Trait(bound) = bound else { return false }; | ||
|
|
||
| KNOWN_TYPE_INFO_BOUNDS.iter().any(|known| bound.path.is_ident(known)) |
There was a problem hiding this comment.
We should just take the last element of the path to improve the detection?
| let fields: syn::punctuated::Punctuated<ConfigValue, syn::Token![,]> = | ||
| inside_config.parse_terminated(ConfigValue::parse, syn::Token![,])?; | ||
| let config_values = fields.iter().collect::<Vec<_>>(); | ||
|
|
||
| let frequencies = config_values.iter().fold(HashMap::new(), |mut map, val| { | ||
| let string_name = match val { | ||
| ConfigValue::WithDefault(_) => "with_default", | ||
| ConfigValue::WithoutAutomaticMetadata(_) => "without_automatic_metadata", | ||
| } | ||
| .to_string(); | ||
| map.entry(string_name).and_modify(|frq| *frq += 1).or_insert(1); | ||
| map | ||
| }); | ||
| let with_default = frequencies.get("with_default").copied().unwrap_or(0) > 0; | ||
| let without_automatic_metadata = | ||
| frequencies.get("without_automatic_metadata").copied().unwrap_or(0) > 0; | ||
|
|
||
| let duplicates = frequencies | ||
| .into_iter() | ||
| .filter_map(|(name, frq)| if frq > 1 { Some(name) } else { None }) | ||
| .collect::<Vec<_>>(); | ||
| if !duplicates.is_empty() { | ||
| let msg = format!("Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates: {}.", duplicates.join(", ")); | ||
| return Err(syn::Error::new(span, msg)); | ||
| } |
There was a problem hiding this comment.
Maybe just having some options would be easier here? But yeah, the code works the way it is written.
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This PR exposes the *unstable* metadata V16. The metadata is exposed under the unstable u32::MAX number. Developers can start experimenting with the new features of the metadata v16. *Please note that this metadata is under development and expect breaking changes until stabilization.* The `ExtrinsicMetadata` trait receives a breaking change. Its associated type `VERSION` is rename to `VERSIONS` and now supports a constant static list of metadata versions. The versions implemented for `UncheckedExtrinsic` are v4 (legacy version) and v5 (new version). For metadata collection, it is assumed that all `TransactionExtensions` are under version 0. Builds on top of: #5274 Closes: #5980 Closes: #5347 Closes: #5285 cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: James Wilson <james@jsdw.me> Co-authored-by: GitHub Action <action@github.com>
This PR exposes the *unstable* metadata V16. The metadata is exposed under the unstable u32::MAX number. Developers can start experimenting with the new features of the metadata v16. *Please note that this metadata is under development and expect breaking changes until stabilization.* The `ExtrinsicMetadata` trait receives a breaking change. Its associated type `VERSION` is rename to `VERSIONS` and now supports a constant static list of metadata versions. The versions implemented for `UncheckedExtrinsic` are v4 (legacy version) and v5 (new version). For metadata collection, it is assumed that all `TransactionExtensions` are under version 0. Builds on top of: paritytech#5274 Closes: paritytech#5980 Closes: paritytech#5347 Closes: paritytech#5285 cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: James Wilson <james@jsdw.me> Co-authored-by: GitHub Action <action@github.com>
This PR exposes the *unstable* metadata V16. The metadata is exposed under the unstable u32::MAX number. Developers can start experimenting with the new features of the metadata v16. *Please note that this metadata is under development and expect breaking changes until stabilization.* The `ExtrinsicMetadata` trait receives a breaking change. Its associated type `VERSION` is rename to `VERSIONS` and now supports a constant static list of metadata versions. The versions implemented for `UncheckedExtrinsic` are v4 (legacy version) and v5 (new version). For metadata collection, it is assumed that all `TransactionExtensions` are under version 0. Builds on top of: paritytech#5274 Closes: paritytech#5980 Closes: paritytech#5347 Closes: paritytech#5285 cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: James Wilson <james@jsdw.me> Co-authored-by: GitHub Action <action@github.com>
This feature is part of the upcoming metadata V16. The associated types of the
Configtrait that require theTypeInfoorParameterbounds are included in the metadata of the pallet. The metadata is not yet exposed to the end-user, however the metadata intermediate representation (IR) contains these types.Developers can opt out of metadata collection of the associated types by specifying
without_metadataoptional attribute to the#[pallet::config].Furthermore, the
without_metadataargument can be used in combination with the newly added#[pallet::include_metadata]attribute to selectively include only certain associated types in the metadata collection.API Design
Builds on top of the PoC: #4358
Closes: #4519
cc @paritytech/subxt-team