From 7e8baee5bddb3e7f6f4b19b8ffd4ef2a1b8f45f0 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 18:05:05 +0300 Subject: [PATCH 01/30] metadata-ir: Introduce PalletAssociatedTypeMetadata Signed-off-by: Alexandru Vasile --- substrate/primitives/metadata-ir/src/types.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs index b05f26ff55d4..9001d4c034e9 100644 --- a/substrate/primitives/metadata-ir/src/types.rs +++ b/substrate/primitives/metadata-ir/src/types.rs @@ -127,6 +127,8 @@ pub struct PalletMetadataIR { pub constants: Vec>, /// Pallet error metadata. pub error: Option>, + /// Config's trait associated types. + pub associated_types: Vec>, /// Define the index of the pallet, this index will be used for the encoding of pallet event, /// call and origin variants. pub index: u8, @@ -145,6 +147,7 @@ impl IntoPortable for PalletMetadataIR { event: self.event.map(|event| event.into_portable(registry)), constants: registry.map_into_portable(self.constants), error: self.error.map(|error| error.into_portable(registry)), + associated_types: registry.map_into_portable(self.associated_types), index: self.index, docs: registry.map_into_portable(self.docs), } @@ -188,6 +191,29 @@ impl IntoPortable for ExtrinsicMetadataIR { } } +/// Metadata of a pallet's associated type. +#[derive(Clone, PartialEq, Eq, Encode, Debug)] +pub struct PalletAssociatedTypeMetadataIR { + /// The name of the associated type. + pub name: T::String, + /// The type of the associated type. + pub ty: T::Type, + /// The documentation of the associated type. + pub docs: Vec, +} + +impl IntoPortable for PalletAssociatedTypeMetadataIR { + type Output = PalletAssociatedTypeMetadataIR; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + PalletAssociatedTypeMetadataIR { + name: self.name.into_portable(registry), + ty: registry.register_type(&self.ty), + docs: registry.map_into_portable(self.docs), + } + } +} + /// Metadata of an extrinsic's signed extension. #[derive(Clone, PartialEq, Eq, Encode, Debug)] pub struct SignedExtensionMetadataIR { From 1c12f1520605ae32454ca8ab6f480ce794285f65 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 18:11:11 +0300 Subject: [PATCH 02/30] frame/config: Add associated types to parsed config Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/config.rs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index 6febaac9ffa3..d4b6169e018c 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -55,6 +55,8 @@ pub struct ConfigDef { pub has_instance: bool, /// Const associated type. pub consts_metadata: Vec, + /// Associated types metadata. + pub associated_types_metadata: Vec, /// Whether the trait has the associated type `Event`, note that those bounds are /// checked: /// * `IsType::RuntimeEvent` @@ -70,6 +72,23 @@ pub struct ConfigDef { pub default_sub_trait: Option, } +/// Input definition for an associated type in pallet config. +pub struct AssociatedTypeMetadataDef { + /// Name of the associated type. + pub ident: syn::Ident, + /// The doc associated. + pub doc: Vec, +} + +impl From<&syn::TraitItemType> for AssociatedTypeMetadataDef { + fn from(trait_ty: &syn::TraitItemType) -> Self { + let ident = trait_ty.ident.clone(); + let doc = get_doc_literals(&trait_ty.attrs); + + Self { ident, doc } + } +} + /// Input definition for a constant in pallet config. pub struct ConstMetadataDef { /// Name of the associated type. @@ -366,6 +385,7 @@ impl ConfigDef { let mut has_event_type = false; let mut consts_metadata = vec![]; + let mut associated_types_metadata = vec![]; let mut default_sub_trait = if enable_default { Some(DefaultTrait { items: Default::default(), @@ -405,7 +425,7 @@ impl ConfigDef { if !enable_default { return Err(syn::Error::new( pallet_attr._bracket.span.join(), - "`#[pallet:no_default]` can only be used if `#[pallet::config(with_default)]` \ + "`#[pallet::no_default]` can only be used if `#[pallet::config(with_default)]` \ has been specified" )) } @@ -437,6 +457,12 @@ impl ConfigDef { } } + if !is_event && !already_constant { + if let syn::TraitItem::Type(ref ty) = trait_item { + associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); + } + } + if !already_no_default && enable_default { default_sub_trait .as_mut() @@ -479,6 +505,7 @@ impl ConfigDef { index, has_instance, consts_metadata, + associated_types_metadata, has_event_type, where_clause, default_sub_trait, From 20b22d8d314df7dfb6590f6d54857190231b77c2 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 18:14:29 +0300 Subject: [PATCH 03/30] frame/expand: Implement associated types expansion Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/expand/config.rs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/substrate/frame/support/procedural/src/pallet/expand/config.rs b/substrate/frame/support/procedural/src/pallet/expand/config.rs index 5cf4035a8f8b..7e67aae93410 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/config.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/config.rs @@ -95,3 +95,48 @@ Consequently, a runtime that wants to include this pallet must implement this tr _ => Default::default(), } } + +/// Generate the metadata for the associated types of the config trait. +/// +/// Implements the `pallet_associated_types_metadata` function for the pallet. +pub fn expand_config_metadata(def: &mut Def) -> proc_macro2::TokenStream { + let frame_support = &def.frame_support; + let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site()); + let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site()); + let pallet_ident = &def.pallet_struct.pallet; + let trait_use_gen = &def.trait_use_generics(proc_macro2::Span::call_site()); + + let mut where_clauses = vec![&def.config.where_clause]; + where_clauses.extend(def.extra_constants.iter().map(|d| &d.where_clause)); + let completed_where_clause = super::merge_where_clauses(&where_clauses); + + let types = def.config.associated_types_metadata.iter().map(|metadata| { + let ident = &metadata.ident; + let ident_str = format!("{}", ident); + + let no_docs = vec![]; + let doc = if cfg!(feature = "no-metadata-docs") { &no_docs } else { &metadata.doc }; + + quote::quote!({ + #frame_support::__private::metadata_ir::PalletAssociatedTypeMetadataIR { + name: #ident_str, + ty: #frame_support::__private::scale_info::meta_type::< + <::#ident + >(), + docs: #frame_support::__private::sp_std::vec![ #( #doc ),* ], + } + }) + }); + + quote::quote!( + impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause { + + #[doc(hidden)] + pub fn pallet_associated_types_metadata() + -> #frame_support::__private::sp_std::vec::Vec<#frame_support::__private::metadata_ir::PalletAssociatedTypeMetadataIR> + { + #frame_support::__private::sp_std::vec![ #( #types ),* ] + } + } + ) +} From 350efce92491f6cb21e641526e45cba339d2fa35 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 18:17:37 +0300 Subject: [PATCH 04/30] frame/expand: Use provided cfgs for the associated types Signed-off-by: Alexandru Vasile --- .../support/procedural/src/pallet/expand/config.rs | 2 ++ .../support/procedural/src/pallet/parse/config.rs | 7 +++++-- .../frame/support/procedural/tools/src/lib.rs | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/expand/config.rs b/substrate/frame/support/procedural/src/pallet/expand/config.rs index 7e67aae93410..1921922781fe 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/config.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/config.rs @@ -113,11 +113,13 @@ pub fn expand_config_metadata(def: &mut Def) -> proc_macro2::TokenStream { let types = def.config.associated_types_metadata.iter().map(|metadata| { let ident = &metadata.ident; let ident_str = format!("{}", ident); + let cfgs = &metadata.cfg; let no_docs = vec![]; let doc = if cfg!(feature = "no-metadata-docs") { &no_docs } else { &metadata.doc }; quote::quote!({ + #( #cfgs ) * #frame_support::__private::metadata_ir::PalletAssociatedTypeMetadataIR { name: #ident_str, ty: #frame_support::__private::scale_info::meta_type::< diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index d4b6169e018c..f92f69c7a1d6 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -16,7 +16,7 @@ // limitations under the License. use super::helper; -use frame_support_procedural_tools::{get_doc_literals, is_using_frame_crate}; +use frame_support_procedural_tools::{get_cfg_attributes, get_doc_literals, is_using_frame_crate}; use quote::ToTokens; use syn::{spanned::Spanned, token, Token}; @@ -78,14 +78,17 @@ pub struct AssociatedTypeMetadataDef { pub ident: syn::Ident, /// The doc associated. pub doc: Vec, + /// The cfg associated. + pub cfg: Vec, } impl From<&syn::TraitItemType> for AssociatedTypeMetadataDef { fn from(trait_ty: &syn::TraitItemType) -> Self { let ident = trait_ty.ident.clone(); let doc = get_doc_literals(&trait_ty.attrs); + let cfg = get_cfg_attributes(&trait_ty.attrs); - Self { ident, doc } + Self { ident, doc, cfg } } } diff --git a/substrate/frame/support/procedural/tools/src/lib.rs b/substrate/frame/support/procedural/tools/src/lib.rs index ea53335a88fd..d1d7efaab01d 100644 --- a/substrate/frame/support/procedural/tools/src/lib.rs +++ b/substrate/frame/support/procedural/tools/src/lib.rs @@ -181,3 +181,17 @@ pub fn get_doc_literals(attrs: &[syn::Attribute]) -> Vec { }) .collect() } + +/// Return all cfg attributes literals found. +pub fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec { + attrs + .iter() + .filter_map(|attr| { + if let syn::Meta::List(meta) = &attr.meta { + meta.path.get_ident().filter(|ident| *ident == "cfg").map(|_| attr.clone()) + } else { + None + } + }) + .collect() +} From 3e97971d0b4840553dbc731d8f27737e130f4411 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 18:33:25 +0300 Subject: [PATCH 05/30] frame/construct_runtime: Extract associated types from pallet config Signed-off-by: Alexandru Vasile --- .../src/construct_runtime/expand/metadata.rs | 11 +++++++++++ .../support/procedural/src/pallet/expand/config.rs | 4 ++-- .../frame/support/procedural/src/pallet/expand/mod.rs | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs index daef1b171617..cbefd9601701 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs @@ -49,6 +49,7 @@ pub fn expand_runtime_metadata( let event = expand_pallet_metadata_events(&filtered_names, runtime, scrate, decl); let constants = expand_pallet_metadata_constants(runtime, decl); let errors = expand_pallet_metadata_errors(runtime, decl); + let associated_types = expand_pallet_metadata_associated_types(runtime, decl); let docs = expand_pallet_metadata_docs(runtime, decl); let attr = decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) @@ -70,6 +71,7 @@ pub fn expand_runtime_metadata( constants: #constants, error: #errors, docs: #docs, + associated_types: #associated_types, } } }) @@ -256,3 +258,12 @@ fn expand_pallet_metadata_docs(runtime: &Ident, decl: &Pallet) -> TokenStream { #path::Pallet::<#runtime #(, #path::#instance)*>::pallet_documentation_metadata() } } + +fn expand_pallet_metadata_associated_types(runtime: &Ident, decl: &Pallet) -> TokenStream { + let path = &decl.path; + let instance = decl.instance.as_ref().into_iter(); + + quote! { + #path::Pallet::<#runtime #(, #path::#instance)*>::pallet_associated_types_metadata() + } +} diff --git a/substrate/frame/support/procedural/src/pallet/expand/config.rs b/substrate/frame/support/procedural/src/pallet/expand/config.rs index 1921922781fe..6b79c4b8b25a 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/config.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/config.rs @@ -99,7 +99,7 @@ Consequently, a runtime that wants to include this pallet must implement this tr /// Generate the metadata for the associated types of the config trait. /// /// Implements the `pallet_associated_types_metadata` function for the pallet. -pub fn expand_config_metadata(def: &mut Def) -> proc_macro2::TokenStream { +pub fn expand_config_metadata(def: &Def) -> proc_macro2::TokenStream { let frame_support = &def.frame_support; let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site()); let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site()); @@ -123,7 +123,7 @@ pub fn expand_config_metadata(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::__private::metadata_ir::PalletAssociatedTypeMetadataIR { name: #ident_str, ty: #frame_support::__private::scale_info::meta_type::< - <::#ident + ::#ident >(), docs: #frame_support::__private::sp_std::vec![ #( #doc ),* ], } diff --git a/substrate/frame/support/procedural/src/pallet/expand/mod.rs b/substrate/frame/support/procedural/src/pallet/expand/mod.rs index 067839c28463..3f9b50f79c0c 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/mod.rs @@ -60,6 +60,7 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { let constants = constants::expand_constants(&mut def); let pallet_struct = pallet_struct::expand_pallet_struct(&mut def); let config = config::expand_config(&mut def); + let associated_types = config::expand_config_metadata(&def); let call = call::expand_call(&mut def); let tasks = tasks::expand_tasks(&mut def); let error = error::expand_error(&mut def); @@ -101,6 +102,7 @@ storage item. Otherwise, all storage items are listed among [*Type Definitions*] #constants #pallet_struct #config + #associated_types #call #tasks #error From 5d8021eb1b58d605e77bb16427092933525092bb Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 19:30:44 +0300 Subject: [PATCH 06/30] frame/pallet: Introduce `config(without_metadata)` Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/config.rs | 4 +- .../procedural/src/pallet/parse/mod.rs | 60 ++++++++++++++++--- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index f92f69c7a1d6..5c11bf8dbcaf 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -36,6 +36,7 @@ mod keyword { syn::custom_keyword!(no_default); syn::custom_keyword!(no_default_bounds); syn::custom_keyword!(constant); + syn::custom_keyword!(without_metadata); } #[derive(Default)] @@ -348,6 +349,7 @@ impl ConfigDef { index: usize, item: &mut syn::Item, enable_default: bool, + without_metadata: bool, ) -> syn::Result { let syn::Item::Trait(item) = item else { let msg = "Invalid pallet::config, expected trait definition"; @@ -460,7 +462,7 @@ impl ConfigDef { } } - if !is_event && !already_constant { + if !without_metadata && !is_event && !already_constant { if let syn::TraitItem::Type(ref ty) = trait_item { associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); } diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index f55b166c7917..fe709bf89ce8 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -43,6 +43,7 @@ pub mod tests; use composite::{keyword::CompositeKeyword, CompositeDef}; use frame_support_procedural_tools::generate_access_from_frame_or_crate; use quote::ToTokens; +use std::collections::HashSet; use syn::spanned::Spanned; /// Parsed definition of a pallet. @@ -109,12 +110,13 @@ impl Def { let pallet_attr: Option = helper::take_first_item_pallet_attr(item)?; match pallet_attr { - Some(PalletAttr::Config(_, with_default)) if config.is_none() => + Some(PalletAttr::Config{ with_default, without_metadata, ..}) if config.is_none() => config = Some(config::ConfigDef::try_from( &frame_system, index, item, with_default, + without_metadata, )?), Some(PalletAttr::Pallet(span)) if pallet_struct.is_none() => { let p = pallet_struct::PalletStructDef::try_from(span, index, item)?; @@ -548,6 +550,7 @@ mod keyword { syn::custom_keyword!(event); syn::custom_keyword!(config); syn::custom_keyword!(with_default); + syn::custom_keyword!(without_metadata); syn::custom_keyword!(hooks); syn::custom_keyword!(inherent); syn::custom_keyword!(error); @@ -561,10 +564,35 @@ mod keyword { syn::custom_keyword!(composite_enum); } +/// The possible values for the `#[pallet::config]` attribute. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum ConfigValue { + /// `#[pallet::config(with_default)]` + WithDefault(keyword::with_default), + /// `#[pallet::config(without_metadata)]` + WithoutMetadata(keyword::without_metadata), +} + +impl syn::parse::Parse for ConfigValue { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + if input.peek(keyword::with_default) { + Ok(ConfigValue::WithDefault(input.parse()?)) + } else if input.peek(keyword::without_metadata) { + Ok(ConfigValue::WithoutMetadata(input.parse()?)) + } else { + Err(input.error("expected `with_default` or `without_metadata`")) + } + } +} + /// Parse attributes for item in pallet module /// syntax must be `pallet::` (e.g. `#[pallet::config]`) enum PalletAttr { - Config(proc_macro2::Span, bool), + Config { + span: proc_macro2::Span, + with_default: bool, + without_metadata: bool, + }, Pallet(proc_macro2::Span), Hooks(proc_macro2::Span), /// A `#[pallet::call]` with optional attributes to specialize the behaviour. @@ -626,7 +654,7 @@ enum PalletAttr { impl PalletAttr { fn span(&self) -> proc_macro2::Span { match self { - Self::Config(span, _) => *span, + Self::Config { span, .. } => *span, Self::Pallet(span) => *span, Self::Hooks(span) => *span, Self::Tasks(span) => *span, @@ -661,13 +689,31 @@ impl syn::parse::Parse for PalletAttr { let lookahead = content.lookahead1(); if lookahead.peek(keyword::config) { let span = content.parse::()?.span(); - let with_default = content.peek(syn::token::Paren); - if with_default { + if content.peek(syn::token::Paren) { let inside_config; + + // Parse (with_default, without_metadata) attributes. let _paren = syn::parenthesized!(inside_config in content); - inside_config.parse::()?; + + let fields: syn::punctuated::Punctuated = + inside_config.parse_terminated(ConfigValue::parse, syn::Token![,])?; + let config_values = fields.iter().collect::>(); + + let with_default = + config_values.iter().any(|v| matches!(v, ConfigValue::WithDefault(_))); + let without_metadata = + config_values.iter().any(|v| matches!(v, ConfigValue::WithoutMetadata(_))); + + // Check for duplicated attributes. + let config_set = config_values.iter().collect::>(); + if config_set.len() != config_values.len() { + return Err(syn::Error::new(span, "Invalid duplicated attribute")) + } + + Ok(PalletAttr::Config { span, with_default, without_metadata }) + } else { + Ok(PalletAttr::Config { span, with_default: false, without_metadata: false }) } - Ok(PalletAttr::Config(span, with_default)) } else if lookahead.peek(keyword::pallet) { Ok(PalletAttr::Pallet(content.parse::()?.span())) } else if lookahead.peek(keyword::hooks) { From 5679244aa99794ef415a17992f2c237ee1f40440 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 19:42:50 +0300 Subject: [PATCH 07/30] frame/pallet: Introduce `#[pallet::include_metadata]` for associated types Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/config.rs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index 5c11bf8dbcaf..65b2b195e94c 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -36,7 +36,7 @@ mod keyword { syn::custom_keyword!(no_default); syn::custom_keyword!(no_default_bounds); syn::custom_keyword!(constant); - syn::custom_keyword!(without_metadata); + syn::custom_keyword!(include_metadata); } #[derive(Default)] @@ -167,6 +167,8 @@ pub enum PalletAttrType { NoBounds(keyword::no_default_bounds), #[peek(keyword::constant, name = "constant")] Constant(keyword::constant), + #[peek(keyword::include_metadata, name = "include_metadata")] + IncludeMetadata(keyword::include_metadata), } /// Parsing for `#[pallet::X]` @@ -349,7 +351,7 @@ impl ConfigDef { index: usize, item: &mut syn::Item, enable_default: bool, - without_metadata: bool, + enable_associated_metadata: bool, ) -> syn::Result { let syn::Item::Trait(item) = item else { let msg = "Invalid pallet::config, expected trait definition"; @@ -406,6 +408,7 @@ impl ConfigDef { let mut already_no_default = false; let mut already_constant = false; let mut already_no_default_bounds = false; + let mut already_collected_associated_type = false; while let Ok(Some(pallet_attr)) = helper::take_first_item_pallet_attr::(trait_item) @@ -426,6 +429,31 @@ impl ConfigDef { trait_item.span(), "Invalid #[pallet::constant] in #[pallet::config], expected type item", )), + (PalletAttrType::IncludeMetadata(_), syn::TraitItem::Type(ref typ)) => { + if is_event { + return Err(syn::Error::new( + pallet_attr._bracket.span.join(), + "Invalid #[pallet::include_metadata] in `type RuntimeEvent`, \ + expected type item. The associated type `RuntimeEvent` is already collected.", + )) + } + + if already_constant { + return Err(syn::Error::new( + pallet_attr._bracket.span.join(), + "Invalid #[pallet::include_metadata] in #[pallet::constant], \ + expected type item. Pallet constant's metadata is already collected.", + )) + } + + already_collected_associated_type = true; + associated_types_metadata.push(AssociatedTypeMetadataDef::from(typ)); + } + (PalletAttrType::IncludeMetadata(_), _) => + return Err(syn::Error::new( + pallet_attr._bracket.span.join(), + "Invalid #[pallet::include_metadata] in #[pallet::config], expected type item", + )), (PalletAttrType::NoDefault(_), _) => { if !enable_default { return Err(syn::Error::new( @@ -462,7 +490,7 @@ impl ConfigDef { } } - if !without_metadata && !is_event && !already_constant { + if !already_collected_associated_type && enable_associated_metadata { if let syn::TraitItem::Type(ref ty) = trait_item { associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); } From 958611ef5a5a5a73ca51878bce4a6e0b1b111740 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 20:13:15 +0300 Subject: [PATCH 08/30] frame/pallet: Include associated type iff bounds contain TypeInfo Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/config.rs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index 65b2b195e94c..2f8a0923b6c5 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -18,7 +18,7 @@ use super::helper; use frame_support_procedural_tools::{get_cfg_attributes, get_doc_literals, is_using_frame_crate}; use quote::ToTokens; -use syn::{spanned::Spanned, token, Token}; +use syn::{spanned::Spanned, token, Token, TraitItemType}; /// List of additional token to be used for parsing. mod keyword { @@ -345,6 +345,23 @@ pub fn replace_self_by_t(input: proc_macro2::TokenStream) -> proc_macro2::TokenS .collect() } +/// Check that the trait item requires the `TypeInfo` bound (or similar). +fn contains_type_info_bound(ty: &TraitItemType) -> bool { + const KNOWN_TYPE_INFO_BOUNDS: &[&str] = &[ + // Explicit TypeInfo trait. + "TypeInfo", + // Implicit known substrate traits that implement type info. + // Note: Aim to keep this list as small as possible. + "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)) + }) +} + impl ConfigDef { pub fn try_from( frame_system: &syn::Path, @@ -429,6 +446,9 @@ impl ConfigDef { trait_item.span(), "Invalid #[pallet::constant] in #[pallet::config], expected type item", )), + // Pallet developer has explicitly requested to include metadata for this associated type. + // + // They must provide a type item that implements `TypeInfo`. (PalletAttrType::IncludeMetadata(_), syn::TraitItem::Type(ref typ)) => { if is_event { return Err(syn::Error::new( @@ -490,9 +510,17 @@ impl ConfigDef { } } - if !already_collected_associated_type && enable_associated_metadata { + // Metadata of associated types is collected by default, iff the associated type + // implements `TypeInfo`, or a similar trait that requires the `TypeInfo` bound. + if !already_collected_associated_type && + enable_associated_metadata && + !is_event && !already_constant + { if let syn::TraitItem::Type(ref ty) = trait_item { - associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); + // Collect the metadata of the associated type if it implements `TypeInfo`. + if contains_type_info_bound(ty) { + associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); + } } } From 7f26b67a7b33dc78c9fc2572a073e77bf14b2610 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 7 Aug 2024 20:13:37 +0300 Subject: [PATCH 09/30] frame/pallet: Proper flag for metdata collection Signed-off-by: Alexandru Vasile --- substrate/frame/support/procedural/src/pallet/parse/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index fe709bf89ce8..bf933bc820f3 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -116,7 +116,7 @@ impl Def { index, item, with_default, - without_metadata, + !without_metadata, )?), Some(PalletAttr::Pallet(span)) if pallet_struct.is_none() => { let p = pallet_struct::PalletStructDef::try_from(span, index, item)?; From cc001f389f80abbdf511b911c2fd04007f1eedcb Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 11:05:10 +0300 Subject: [PATCH 10/30] frame/tests/ui: Fix type in test Signed-off-by: Alexandru Vasile --- .../tests/pallet_ui/no_default_but_missing_with_default.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/test/tests/pallet_ui/no_default_but_missing_with_default.stderr b/substrate/frame/support/test/tests/pallet_ui/no_default_but_missing_with_default.stderr index e8df28a3046f..1b066bbe9fb8 100644 --- a/substrate/frame/support/test/tests/pallet_ui/no_default_but_missing_with_default.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/no_default_but_missing_with_default.stderr @@ -1,4 +1,4 @@ -error: `#[pallet:no_default]` can only be used if `#[pallet::config(with_default)]` has been specified +error: `#[pallet::no_default]` can only be used if `#[pallet::config(with_default)]` has been specified --> tests/pallet_ui/no_default_but_missing_with_default.rs:26:4 | 26 | #[pallet::no_default] From b2803e2f2f785702de70e0825274eeffdd014d46 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 11:12:19 +0300 Subject: [PATCH 11/30] frame/tests/ui: Check config without metadata Signed-off-by: Alexandru Vasile --- .../pallet_ui/pass/config_without_metadata.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs b/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs new file mode 100644 index 000000000000..9304b2ccc9bf --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/pass/config_without_metadata.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + + #[pallet::config(without_metadata)] + pub trait Config: frame_system::Config { + #[pallet::constant] + type MyGetParam2: Get; + } + + #[pallet::pallet] + pub struct Pallet(_); +} + +fn main() {} From 94007d8c3189d5781db5ffe9d31d54cdc8a56cbd Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 11:12:34 +0300 Subject: [PATCH 12/30] frame/tests/ui: Check config with multiple attributes Signed-off-by: Alexandru Vasile --- .../pallet_ui/pass/config_multiple_attr.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs diff --git a/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs b/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs new file mode 100644 index 000000000000..1eee25b333e4 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/pass/config_multiple_attr.rs @@ -0,0 +1,32 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + + #[pallet::config(with_default, without_metadata)] + pub trait Config: frame_system::Config { + #[pallet::constant] + type MyGetParam2: Get; + } + + #[pallet::pallet] + pub struct Pallet(_); +} + +fn main() {} From 75d26971b5e5520fbf8937a74665f1f1018e32c8 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 11:50:00 +0300 Subject: [PATCH 13/30] frame/tests/ui: Add negative test for duplicate attributes in config Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/mod.rs | 5 ++- .../tests/pallet_ui/config_duplicate_attr.rs | 39 +++++++++++++++++++ .../pallet_ui/config_duplicate_attr.stderr | 5 +++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index bf933bc820f3..6f5a599b08ee 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -707,7 +707,10 @@ impl syn::parse::Parse for PalletAttr { // Check for duplicated attributes. let config_set = config_values.iter().collect::>(); if config_set.len() != config_values.len() { - return Err(syn::Error::new(span, "Invalid duplicated attribute")) + return Err(syn::Error::new( + span, + "Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates.", + )); } Ok(PalletAttr::Config { span, with_default, without_metadata }) diff --git a/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.rs b/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.rs new file mode 100644 index 000000000000..3d7b4f87d22c --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.rs @@ -0,0 +1,39 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default, without_metadata, without_metadata)] + pub trait Config: frame_system::Config { + #[pallet::constant] + type MyGetParam2: Get; + } + + #[pallet::pallet] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::call] + impl Pallet {} +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr new file mode 100644 index 000000000000..7217aa370ed5 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr @@ -0,0 +1,5 @@ +error: Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates. + --> tests/pallet_ui/config_duplicate_attr.rs:23:12 + | +23 | #[pallet::config(with_default, without_metadata, without_metadata)] + | ^^^^^^ From ebcb4a0aa5e6c65d17f15d49262bb4b4b3482964 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 11:53:49 +0300 Subject: [PATCH 14/30] frame/tests/ui: Add negative test for collecting metadata from constants Signed-off-by: Alexandru Vasile --- .../pallet_ui/config_metadata_on_constants.rs | 40 +++++++++++++++++++ .../config_metadata_on_constants.stderr | 5 +++ 2 files changed, 45 insertions(+) create mode 100644 substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.stderr diff --git a/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs new file mode 100644 index 000000000000..a4ff02aeb1cd --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs @@ -0,0 +1,40 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + #[pallet::constant] + #[pallet::include_metadata] + type MyGetParam2: Get; + } + + #[pallet::pallet] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::call] + impl Pallet {} +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.stderr b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.stderr new file mode 100644 index 000000000000..ac27bfe89a08 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.stderr @@ -0,0 +1,5 @@ +error: Invalid #[pallet::include_metadata] in #[pallet::constant], expected type item. Pallet constant's metadata is already collected. + --> tests/pallet_ui/config_metadata_on_constants.rs:26:10 + | +26 | #[pallet::include_metadata] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ From 51150217bf9cf8869a141e1cfe5f2dcd063e6594 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 11:58:52 +0300 Subject: [PATCH 15/30] frame/tests/ui: Add negative test for metadata collection on events Signed-off-by: Alexandru Vasile --- .../pallet_ui/config_metadata_on_events.rs | 43 +++++++++++++++++++ .../config_metadata_on_events.stderr | 5 +++ 2 files changed, 48 insertions(+) create mode 100644 substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.stderr diff --git a/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.rs b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.rs new file mode 100644 index 000000000000..d91f86771bf6 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.rs @@ -0,0 +1,43 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + #[pallet::no_default_bounds] + #[pallet::include_metadata] + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + #[pallet::constant] + type MyGetParam2: Get; + } + + #[pallet::pallet] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::call] + impl Pallet {} +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.stderr b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.stderr new file mode 100644 index 000000000000..0c79929bca37 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_events.stderr @@ -0,0 +1,5 @@ +error: Invalid #[pallet::include_metadata] in `type RuntimeEvent`, expected type item. The associated type `RuntimeEvent` is already collected. + --> tests/pallet_ui/config_metadata_on_events.rs:26:4 + | +26 | #[pallet::include_metadata] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ From aba029a471f26dd5e1c4286104eb53029ceafd15 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:07:25 +0300 Subject: [PATCH 16/30] frame/tests: Check PalletAssociatedTypeMetadataIR collection Signed-off-by: Alexandru Vasile --- .../tests/pallet_associated_types_metadata.rs | 269 ++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 substrate/frame/support/test/tests/pallet_associated_types_metadata.rs diff --git a/substrate/frame/support/test/tests/pallet_associated_types_metadata.rs b/substrate/frame/support/test/tests/pallet_associated_types_metadata.rs new file mode 100644 index 000000000000..9de5d79ad34c --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_associated_types_metadata.rs @@ -0,0 +1,269 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use frame_support::{derive_impl, traits::ConstU32}; +use scale_info::meta_type; +use sp_metadata_ir::PalletAssociatedTypeMetadataIR; + +pub type BlockNumber = u64; +pub type Header = sp_runtime::generic::Header; +pub type Block = sp_runtime::generic::Block; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; + +/// Pallet without collectable associated types. +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + // Runtime events already propagated to the metadata. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + // Constants are already propagated. + #[pallet::constant] + type MyGetParam2: Get; + } + + #[pallet::event] + pub enum Event { + TestEvent, + } +} + +/// Pallet with default collectable associated types. +#[frame_support::pallet] +pub mod pallet2 { + use frame_support::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + // Runtime events already propagated to the metadata. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + // Constants are already propagated. + #[pallet::constant] + type MyGetParam2: Get; + + // Associated type included by default, because it requires TypeInfo bound. + /// Nonce doc. + type Nonce: TypeInfo; + + // Associated type included by default, because it requires + // Parameter bound (indirect TypeInfo). + type AccountData: Parameter; + + // Associated type without metadata bounds, not included. + type NotIncluded: From; + } + + #[pallet::event] + pub enum Event { + TestEvent, + } +} + +/// Pallet with implicit collectable associated types. +#[frame_support::pallet] +pub mod pallet3 { + use frame_support::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + // Associated types are not collected by default. + #[pallet::config(without_metadata)] + pub trait Config: frame_system::Config { + // Runtime events already propagated to the metadata. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + // Constants are already propagated. + #[pallet::constant] + type MyGetParam2: Get; + + // Explicitly include associated types. + #[pallet::include_metadata] + type Nonce: TypeInfo; + + type AccountData: Parameter; + + type NotIncluded: From; + } + + #[pallet::event] + pub enum Event { + TestEvent, + } +} + +impl pallet::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MyGetParam2 = ConstU32<10>; +} + +impl pallet2::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MyGetParam2 = ConstU32<10>; + type Nonce = u64; + type AccountData = u16; + type NotIncluded = u8; +} + +impl pallet3::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MyGetParam2 = ConstU32<10>; + type Nonce = u64; + type AccountData = u16; + type NotIncluded = u8; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Runtime { + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type BaseCallFilter = frame_support::traits::Everything; + type RuntimeOrigin = RuntimeOrigin; + type Nonce = u64; + type RuntimeCall = RuntimeCall; + type Hash = sp_runtime::testing::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = sp_runtime::traits::IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +frame_support::construct_runtime!( + pub enum Runtime + { + System: frame_system, + Example: pallet, + DefaultInclusion: pallet2, + ExplicitInclusion: pallet3, + } +); + +#[test] +fn associated_types_metadata() { + fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { + if cfg!(feature = "no-metadata-docs") { + vec![] + } else { + doc + } + } + + let ir = Runtime::metadata_ir(); + + // No associated types to collect. + let pallet = ir.pallets.iter().find(|pallet| pallet.name == "Example").unwrap(); + pretty_assertions::assert_eq!(pallet.associated_types, vec![]); + + // Collect by default types that implement TypeInfo or Parameter. + let pallet = ir.pallets.iter().find(|pallet| pallet.name == "DefaultInclusion").unwrap(); + pretty_assertions::assert_eq!( + pallet.associated_types, + vec![ + PalletAssociatedTypeMetadataIR { + name: "Nonce", + ty: meta_type::(), + docs: maybe_docs(vec![" Nonce doc."]), + }, + PalletAssociatedTypeMetadataIR { + name: "AccountData", + ty: meta_type::(), + docs: vec![], + } + ] + ); + + // Explicitly include associated types. + let pallet = ir.pallets.iter().find(|pallet| pallet.name == "ExplicitInclusion").unwrap(); + pretty_assertions::assert_eq!( + pallet.associated_types, + vec![PalletAssociatedTypeMetadataIR { + name: "Nonce", + ty: meta_type::(), + docs: vec![], + }] + ); + + // Check system pallet. + let pallet = ir.pallets.iter().find(|pallet| pallet.name == "System").unwrap(); + pretty_assertions::assert_eq!( + pallet.associated_types, + vec![ + PalletAssociatedTypeMetadataIR { + name: "RuntimeCall", + ty: meta_type::(), + docs: maybe_docs(vec![" The aggregated `RuntimeCall` type."]), + }, + PalletAssociatedTypeMetadataIR { + name: "Nonce", + ty: meta_type::(), + docs: maybe_docs(vec![" This stores the number of previous transactions associated with a sender account."]), + }, + PalletAssociatedTypeMetadataIR { + name: "Hash", + ty: meta_type::(), + docs: maybe_docs(vec![" The output of the `Hashing` function."]), + }, + PalletAssociatedTypeMetadataIR { + name: "Hashing", + ty: meta_type::(), + docs: maybe_docs(vec![" The hashing system (algorithm) being used in the runtime (e.g. Blake2)."]), + }, + PalletAssociatedTypeMetadataIR { + name: "AccountId", + ty: meta_type::(), + docs: maybe_docs(vec![" The user account identifier type for the runtime."]), + }, + PalletAssociatedTypeMetadataIR { + name: "Block", + ty: meta_type::(), + docs: maybe_docs(vec![ + " The Block type used by the runtime. This is used by `construct_runtime` to retrieve the", + " extrinsics or other block specific data as needed.", + ]), + }, + PalletAssociatedTypeMetadataIR { + name: "AccountData", + ty: meta_type::<()>(), + docs: maybe_docs(vec![ + " Data to be associated with an account (other than nonce/transaction counter, which this", + " pallet does regardless).", + ]), + }, + ] + ); +} From 6502c830889275418dc3392881aa52ce0da96dcf Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:27:56 +0300 Subject: [PATCH 17/30] frame/support: Add documentation Signed-off-by: Alexandru Vasile --- substrate/frame/support/procedural/src/lib.rs | 9 +++ substrate/frame/support/src/lib.rs | 62 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index ef99faee86ae..05f6333cd275 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -955,6 +955,15 @@ pub fn event(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } +/// +/// --- +/// +/// Documentation for this macro can be found at `frame_support::pallet_macros::include_metadata`. +#[proc_macro_attribute] +pub fn include_metadata(_: TokenStream, _: TokenStream) -> TokenStream { + pallet_macro_stub() +} + /// /// --- /// diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index bd571571ee24..2d882dd224f5 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -1556,6 +1556,57 @@ pub mod pallet_macros { /// * [`frame_support::derive_impl`]. /// * [`#[pallet::no_default]`](`no_default`) /// * [`#[pallet::no_default_bounds]`](`no_default_bounds`) + /// + /// ## Optional: `without_metadata` + /// + /// By default, the associated types of the `Config` trait that require the `TypeInfo` or + /// `Parameter` bounds are included in the metadata of the pallet. Please note that the + /// `RuntimeEvent` and constants are already included in the metadata. + /// + /// The optional `without_metadata` argument can be used to exclude these associated types + /// from the metadata collection. + /// + /// Furthermore, the `without_metadata` argument can be used in combination with the + /// [`#[pallet::include_metadata]`](`include_metadata`) attribute to selectively include + /// only certain associated types in the metadata collection. + /// + /// ``` + /// #[frame_support::pallet] + /// mod pallet { + /// # use frame_support::pallet_prelude::*; + /// # use frame_system::pallet_prelude::*; + /// # use core::fmt::Debug; + /// # use frame_support::traits::Contains; + /// # + /// # pub trait SomeMoreComplexBound {} + /// # + /// #[pallet::pallet] + /// pub struct Pallet(_); + /// + /// #[pallet::config(with_default, without_metadata)] // <- with_default and without_metadata are optional + /// pub trait Config: frame_system::Config { + /// /// The overarching event type. + /// #[pallet::no_default_bounds] // Default with bounds is not supported for RuntimeEvent + /// type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// + /// /// A simple type. + /// // Type that would have been included in metadata, but is now excluded. + /// type SimpleType: From + TypeInfo; + /// + /// // The `pallet::include_metadata` is used to selectively include this type in metadata. + /// #[pallet::include_metadata] + /// type SelectivelyInclude: From + TypeInfo; + /// } + /// + /// #[pallet::event] + /// pub enum Event { + /// SomeEvent(u16, u32), + /// } + /// } + /// ``` + /// + /// For more information, see: + /// * [`#[pallet::include_metadata]`](`include_metadata`) pub use frame_support_procedural::config; /// Allows defining an enum that gets composed as an aggregate enum by `construct_runtime`. @@ -1935,6 +1986,17 @@ pub mod pallet_macros { /// `Member`, available in [`frame_support::pallet_prelude`]. pub use frame_support_procedural::event; + /// Selectively includes associated types in the metadata. + /// + /// The optional attribute allows you to selectively include associated types in the + /// metadata. This can be attached to trait items that implement `TypeInfo`. + /// + /// By default all collectable associated types are included in the metadata. + /// + /// This attribute can be used in combination with the + /// [`#[pallet::config(without_metadata)]`](`config`). + pub use frame_support_procedural::include_metadata; + /// Allows a pallet to declare a set of functions as a *dispatchable extrinsic*. /// /// In slightly simplified terms, this macro declares the set of "transactions" of a From e9571cbdd505ebfb57c567c988245c97413ae621 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:33:52 +0300 Subject: [PATCH 18/30] Add PRdoc Signed-off-by: Alexandru Vasile --- prdoc/pr_5274.prdoc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 prdoc/pr_5274.prdoc diff --git a/prdoc/pr_5274.prdoc b/prdoc/pr_5274.prdoc new file mode 100644 index 000000000000..44c7085ef9d7 --- /dev/null +++ b/prdoc/pr_5274.prdoc @@ -0,0 +1,24 @@ +title: Enrich metadata IR with associated types of config traits + +doc: + - audience: Runtime Dev + description: | + This feature is part of the upcoming metadata V16. The associated types of the `Config` trait that require the `TypeInfo` + or `Parameter` bounds 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_metadata` optional attribute + to the `#[pallet::config]`. + + Furthermore, the `without_metadata` argument can be used in combination with the newly added `#[pallet::include_metadata]` + attribute to selectively include only certain associated types in the metadata collection. + +crates: + - name: frame-support-procedural + bump: minor + - name: frame-support-procedural-tools + bump: minor + - name: sp-metadata-ir + bump: minor + - name: pallet-assets + bump: minor \ No newline at end of file From 7429eb7102518da7f74390b2b67ac5fa0d0c6a3f Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:48:35 +0300 Subject: [PATCH 19/30] Update prdoc Signed-off-by: Alexandru Vasile --- prdoc/pr_5274.prdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prdoc/pr_5274.prdoc b/prdoc/pr_5274.prdoc index 44c7085ef9d7..f3ec67da4a42 100644 --- a/prdoc/pr_5274.prdoc +++ b/prdoc/pr_5274.prdoc @@ -15,10 +15,10 @@ doc: crates: - name: frame-support-procedural - bump: minor + bump: patch - name: frame-support-procedural-tools - bump: minor + bump: patch - name: sp-metadata-ir - bump: minor + bump: patch - name: pallet-assets - bump: minor \ No newline at end of file + bump: patch From 8a0c138490971761e52b74bf729686b7c5eff84c Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:48:51 +0300 Subject: [PATCH 20/30] prdoc: Remove unneeded crate Signed-off-by: Alexandru Vasile --- prdoc/pr_5274.prdoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/prdoc/pr_5274.prdoc b/prdoc/pr_5274.prdoc index f3ec67da4a42..85f7d1cc2862 100644 --- a/prdoc/pr_5274.prdoc +++ b/prdoc/pr_5274.prdoc @@ -20,5 +20,3 @@ crates: bump: patch - name: sp-metadata-ir bump: patch - - name: pallet-assets - bump: patch From c6c1800fca82bb2003097f86811e9f53aefb5df2 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:49:23 +0300 Subject: [PATCH 21/30] prdoc: Include frame-support Signed-off-by: Alexandru Vasile --- prdoc/pr_5274.prdoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prdoc/pr_5274.prdoc b/prdoc/pr_5274.prdoc index 85f7d1cc2862..304e3e3f779e 100644 --- a/prdoc/pr_5274.prdoc +++ b/prdoc/pr_5274.prdoc @@ -14,6 +14,8 @@ doc: attribute to selectively include only certain associated types in the metadata collection. crates: + - name: frame-support + bump: patch - name: frame-support-procedural bump: patch - name: frame-support-procedural-tools From 90c100c0c67c0d273613292093f574040d923fcd Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 8 Aug 2024 13:57:45 +0300 Subject: [PATCH 22/30] Prupdate Signed-off-by: Alexandru Vasile --- prdoc/pr_5274.prdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prdoc/pr_5274.prdoc b/prdoc/pr_5274.prdoc index 304e3e3f779e..fb76ce661b4e 100644 --- a/prdoc/pr_5274.prdoc +++ b/prdoc/pr_5274.prdoc @@ -21,4 +21,4 @@ crates: - name: frame-support-procedural-tools bump: patch - name: sp-metadata-ir - bump: patch + bump: major From f703e4debebc402884edeb95a0fdf4a90a1245c5 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:53:35 +0300 Subject: [PATCH 23/30] Update substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- .../test/tests/pallet_ui/config_metadata_on_constants.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs index a4ff02aeb1cd..5452479b76e7 100644 --- a/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs +++ b/substrate/frame/support/test/tests/pallet_ui/config_metadata_on_constants.rs @@ -23,7 +23,7 @@ mod pallet { #[pallet::config] pub trait Config: frame_system::Config { #[pallet::constant] - #[pallet::include_metadata] + #[pallet::include_metadata] type MyGetParam2: Get; } From fbd36bc6f624be0e867652aee00ba961071370f7 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:53:43 +0300 Subject: [PATCH 24/30] Update substrate/frame/support/procedural/src/pallet/expand/config.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- substrate/frame/support/procedural/src/pallet/expand/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/procedural/src/pallet/expand/config.rs b/substrate/frame/support/procedural/src/pallet/expand/config.rs index 6b79c4b8b25a..07c48a556005 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/config.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/config.rs @@ -112,7 +112,7 @@ pub fn expand_config_metadata(def: &Def) -> proc_macro2::TokenStream { let types = def.config.associated_types_metadata.iter().map(|metadata| { let ident = &metadata.ident; - let ident_str = format!("{}", ident); + let ident_str = ident.to_string(); let cfgs = &metadata.cfg; let no_docs = vec![]; From 6be9ef3fe09c14d11fce7b0c773bab8e99cbe6c7 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:54:18 +0300 Subject: [PATCH 25/30] Update substrate/frame/support/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- substrate/frame/support/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 232e52b267be..c8a7a39681b7 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -1566,8 +1566,7 @@ pub mod pallet_macros { /// ## Optional: `without_metadata` /// /// By default, the associated types of the `Config` trait that require the `TypeInfo` or - /// `Parameter` bounds are included in the metadata of the pallet. Please note that the - /// `RuntimeEvent` and constants are already included in the metadata. + /// `Parameter` bounds are included in the metadata of the pallet. /// /// The optional `without_metadata` argument can be used to exclude these associated types /// from the metadata collection. From c9b0e2a7d3975b27ac67e2506dd9a9c4e7a9c123 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 1 Oct 2024 18:21:21 +0300 Subject: [PATCH 26/30] frame/parse: Include duplicates in error message Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/mod.rs | 32 ++++++++++++------- .../pallet_ui/config_duplicate_attr.stderr | 2 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index 5a7ccf0e5c64..5ff7281311ca 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -43,7 +43,7 @@ pub mod tests; use composite::{keyword::CompositeKeyword, CompositeDef}; use frame_support_procedural_tools::generate_access_from_frame_or_crate; use quote::ToTokens; -use std::collections::HashSet; +use std::collections::HashMap; use syn::spanned::Spanned; /// Parsed definition of a pallet. @@ -698,18 +698,26 @@ impl syn::parse::Parse for PalletAttr { inside_config.parse_terminated(ConfigValue::parse, syn::Token![,])?; let config_values = fields.iter().collect::>(); - let with_default = - config_values.iter().any(|v| matches!(v, ConfigValue::WithDefault(_))); + let frequencies = config_values.iter().fold(HashMap::new(), |mut map, val| { + let string_name = match val { + ConfigValue::WithDefault(_) => "with_default", + ConfigValue::WithoutMetadata(_) => "without_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_metadata = - config_values.iter().any(|v| matches!(v, ConfigValue::WithoutMetadata(_))); - - // Check for duplicated attributes. - let config_set = config_values.iter().collect::>(); - if config_set.len() != config_values.len() { - return Err(syn::Error::new( - span, - "Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates.", - )); + frequencies.get("without_metadata").copied().unwrap_or(0) > 0; + + let duplicates = frequencies + .into_iter() + .filter_map(|(name, frq)| if frq > 1 { Some(name) } else { None }) + .collect::>(); + 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)); } Ok(PalletAttr::Config { span, with_default, without_metadata }) diff --git a/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr index 7217aa370ed5..0fdbd94dc816 100644 --- a/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/config_duplicate_attr.stderr @@ -1,4 +1,4 @@ -error: Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates. +error: Invalid duplicated attribute for `#[pallet::config]`. Please remove duplicates: without_metadata. --> tests/pallet_ui/config_duplicate_attr.rs:23:12 | 23 | #[pallet::config(with_default, without_metadata, without_metadata)] From 0382d322d7ec98db16e01b1b9389ccfee00869b7 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 1 Oct 2024 18:25:27 +0300 Subject: [PATCH 27/30] frame/parse: Change parsing with lookahead Signed-off-by: Alexandru Vasile --- .../frame/support/procedural/src/pallet/parse/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index 5ff7281311ca..02aa7f7843e2 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -574,10 +574,12 @@ enum ConfigValue { impl syn::parse::Parse for ConfigValue { fn parse(input: syn::parse::ParseStream) -> syn::Result { - if input.peek(keyword::with_default) { - Ok(ConfigValue::WithDefault(input.parse()?)) + let lookahead = input.lookahead1(); + + if lookahead.peek(keyword::with_default) { + input.parse().map(ConfigValue::WithDefault) } else if input.peek(keyword::without_metadata) { - Ok(ConfigValue::WithoutMetadata(input.parse()?)) + input.parse().map(ConfigValue::WithoutMetadata) } else { Err(input.error("expected `with_default` or `without_metadata`")) } From e52ba1dedbf45f27ee02f5ce13e33d798e3aa0b4 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 1 Oct 2024 18:30:46 +0300 Subject: [PATCH 28/30] frame/lib: Remove links to include_metadata Signed-off-by: Alexandru Vasile --- substrate/frame/support/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index c8a7a39681b7..41dcc9d3257d 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -1609,9 +1609,6 @@ pub mod pallet_macros { /// } /// } /// ``` - /// - /// For more information, see: - /// * [`#[pallet::include_metadata]`](`include_metadata`) pub use frame_support_procedural::config; /// Allows defining an enum that gets composed as an aggregate enum by `construct_runtime`. From 45f86ebe1714f0c09da78eac7fbcc44acef21eaf Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 1 Oct 2024 19:06:14 +0300 Subject: [PATCH 29/30] pallet/parse: Collect associated metadata while taking constants into account Signed-off-by: Alexandru Vasile --- .../procedural/src/pallet/parse/config.rs | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index 713c58f201f8..d85480731d3c 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -427,7 +427,7 @@ impl ConfigDef { let mut already_no_default = false; let mut already_constant = false; let mut already_no_default_bounds = false; - let mut already_collected_associated_type = false; + let mut already_collected_associated_type = None; while let Ok(Some(pallet_attr)) = helper::take_first_item_pallet_attr::(trait_item) @@ -452,23 +452,7 @@ impl ConfigDef { // // They must provide a type item that implements `TypeInfo`. (PalletAttrType::IncludeMetadata(_), syn::TraitItem::Type(ref typ)) => { - if is_event { - return Err(syn::Error::new( - pallet_attr._bracket.span.join(), - "Invalid #[pallet::include_metadata] in `type RuntimeEvent`, \ - expected type item. The associated type `RuntimeEvent` is already collected.", - )) - } - - if already_constant { - return Err(syn::Error::new( - pallet_attr._bracket.span.join(), - "Invalid #[pallet::include_metadata] in #[pallet::constant], \ - expected type item. Pallet constant's metadata is already collected.", - )) - } - - already_collected_associated_type = true; + already_collected_associated_type = Some(pallet_attr._bracket.span.join()); associated_types_metadata.push(AssociatedTypeMetadataDef::from(typ)); } (PalletAttrType::IncludeMetadata(_), _) => @@ -512,16 +496,32 @@ impl ConfigDef { } } - // Metadata of associated types is collected by default, iff the associated type - // implements `TypeInfo`, or a similar trait that requires the `TypeInfo` bound. - if !already_collected_associated_type && - enable_associated_metadata && - !is_event && !already_constant - { - if let syn::TraitItem::Type(ref ty) = trait_item { - // Collect the metadata of the associated type if it implements `TypeInfo`. - if contains_type_info_bound(ty) { - associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); + if let Some(span) = already_collected_associated_type { + // Events and constants are already propagated to the metadata + if is_event { + return Err(syn::Error::new( + span, + "Invalid #[pallet::include_metadata] in `type RuntimeEvent`, \ + expected type item. The associated type `RuntimeEvent` is already collected.", + )) + } + + if already_constant { + return Err(syn::Error::new( + span, + "Invalid #[pallet::include_metadata] in #[pallet::constant], \ + expected type item. Pallet constant's metadata is already collected.", + )) + } + } else { + // Metadata of associated types is collected by default, if the associated type + // implements `TypeInfo`, or a similar trait that requires the `TypeInfo` bound. + if enable_associated_metadata && !is_event && !already_constant { + if let syn::TraitItem::Type(ref ty) = trait_item { + // Collect the metadata of the associated type if it implements `TypeInfo`. + if contains_type_info_bound(ty) { + associated_types_metadata.push(AssociatedTypeMetadataDef::from(ty)); + } } } } From fb8b2d4de1f1cfae35a501085987f41f8af621d0 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 1 Oct 2024 19:17:35 +0300 Subject: [PATCH 30/30] pallet/parse: Reverse enable metadata flag to disable metadata Signed-off-by: Alexandru Vasile --- substrate/frame/support/procedural/src/pallet/parse/config.rs | 4 ++-- substrate/frame/support/procedural/src/pallet/parse/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/parse/config.rs b/substrate/frame/support/procedural/src/pallet/parse/config.rs index d85480731d3c..444e324844c4 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/config.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/config.rs @@ -370,7 +370,7 @@ impl ConfigDef { index: usize, item: &mut syn::Item, enable_default: bool, - enable_associated_metadata: bool, + disable_associated_metadata: bool, ) -> syn::Result { let syn::Item::Trait(item) = item else { let msg = "Invalid pallet::config, expected trait definition"; @@ -516,7 +516,7 @@ impl ConfigDef { } else { // Metadata of associated types is collected by default, if the associated type // implements `TypeInfo`, or a similar trait that requires the `TypeInfo` bound. - if enable_associated_metadata && !is_event && !already_constant { + if !disable_associated_metadata && !is_event && !already_constant { if let syn::TraitItem::Type(ref ty) = trait_item { // Collect the metadata of the associated type if it implements `TypeInfo`. if contains_type_info_bound(ty) { diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index 02aa7f7843e2..8f12fe7bdc93 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -115,7 +115,7 @@ impl Def { index, item, with_default, - !without_metadata, + without_metadata, )?), Some(PalletAttr::Pallet(span)) if pallet_struct.is_none() => { let p = pallet_struct::PalletStructDef::try_from(span, index, item)?;