// 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. //! Proc macro of Support code for the runtime. #![recursion_limit = "512"] #![deny(rustdoc::broken_intra_doc_links)] mod benchmark; mod construct_runtime; mod crate_version; mod derive_impl; mod dummy_part_checker; mod dynamic_params; mod key_prefix; mod match_and_insert; mod no_bound; mod pallet; mod pallet_error; mod runtime; mod storage_alias; mod transactional; mod tt_macro; use frame_support_procedural_tools::generate_access_from_frame_or_crate; use macro_magic::{import_tokens_attr, import_tokens_attr_verbatim}; use proc_macro::TokenStream; use quote::{quote, ToTokens}; use std::{cell::RefCell, str::FromStr}; use syn::{parse_macro_input, Error, ItemImpl, ItemMod, TraitItemType}; pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; thread_local! { /// A global counter, can be used to generate a relatively unique identifier. static COUNTER: RefCell = RefCell::new(Counter(0)); } /// Counter to generate a relatively unique identifier for macros. This is necessary because /// declarative macros gets hoisted to the crate root, which shares the namespace with other pallets /// containing the very same macros. struct Counter(u64); impl Counter { fn inc(&mut self) -> u64 { let ret = self.0; self.0 += 1; ret } } /// Get the value from the given environment variable set by cargo. /// /// The value is parsed into the requested destination type. fn get_cargo_env_var(version_env: &str) -> std::result::Result { let version = std::env::var(version_env) .unwrap_or_else(|_| panic!("`{}` is always set by cargo; qed", version_env)); T::from_str(&version).map_err(drop) } /// Generate the counter_prefix related to the storage. /// counter_prefix is used by counted storage map. fn counter_prefix(prefix: &str) -> String { format!("CounterFor{}", prefix) } /// Construct a runtime, with the given name and the given pallets. /// /// The parameters here are specific types for `Block`, `NodeBlock`, and `UncheckedExtrinsic` /// and the pallets that are used by the runtime. /// `Block` is the block type that is used in the runtime and `NodeBlock` is the block type /// that is used in the node. For instance they can differ in the extrinsics type. /// /// # Example: /// /// ```ignore /// construct_runtime!( /// pub enum Runtime where /// Block = Block, /// NodeBlock = node::Block, /// UncheckedExtrinsic = UncheckedExtrinsic /// { /// System: frame_system::{Pallet, Call, Event, Config} = 0, /// Test: path::to::test::{Pallet, Call} = 1, /// /// // Pallets with instances. /// Test2_Instance1: test2::::{Pallet, Call, Storage, Event, Config, Origin}, /// Test2_DefaultInstance: test2::{Pallet, Call, Storage, Event, Config, Origin} = 4, /// /// // Pallets declared with `pallet` attribute macro: no need to define the parts /// Test3_Instance1: test3::, /// Test3_DefaultInstance: test3, /// /// // with `exclude_parts` keyword some part can be excluded. /// Test4_Instance1: test4:: exclude_parts { Call, Origin }, /// Test4_DefaultInstance: test4 exclude_parts { Storage }, /// /// // with `use_parts` keyword, a subset of the pallet parts can be specified. /// Test4_Instance1: test4:: use_parts { Pallet, Call}, /// Test4_DefaultInstance: test4 use_parts { Pallet }, /// } /// ) /// ``` /// /// Each pallet is declared as such: /// * `Identifier`: name given to the pallet that uniquely identifies it. /// /// * `:`: colon separator /// /// * `path::to::pallet`: identifiers separated by colons which declare the path to a pallet /// definition. /// /// * `::` optional: specify the instance of the pallet to use. If not specified it will /// use the default instance (or the only instance in case of non-instantiable pallets). /// /// * `::{ Part1, Part2, .. }` optional if pallet declared with `frame_support::pallet`: Comma /// separated parts declared with their generic. If a pallet is declared with /// `frame_support::pallet` macro then the parts can be automatically derived if not explicitly /// provided. We provide support for the following module parts in a pallet: /// /// - `Pallet` - Required for all pallets /// - `Call` - If the pallet has callable functions /// - `Storage` - If the pallet uses storage /// - `Event` or `Event` (if the event is generic) - If the pallet emits events /// - `Origin` or `Origin` (if the origin is generic) - If the pallet has instantiable origins /// - `Config` or `Config` (if the config is generic) - If the pallet builds the genesis /// storage with `GenesisConfig` /// - `Inherent` - If the pallet provides/can check inherents. /// - `ValidateUnsigned` - If the pallet validates unsigned extrinsics. /// /// It is important to list these parts here to export them correctly in the metadata or to make /// the pallet usable in the runtime. /// /// * `exclude_parts { Part1, Part2 }` optional: comma separated parts without generics. I.e. one of /// `Pallet`, `Call`, `Storage`, `Event`, `Origin`, `Config`, `Inherent`, `ValidateUnsigned`. It /// is incompatible with `use_parts`. This specifies the part to exclude. In order to select /// subset of the pallet parts. /// /// For example excluding the part `Call` can be useful if the runtime doesn't want to make the /// pallet calls available. /// /// * `use_parts { Part1, Part2 }` optional: comma separated parts without generics. I.e. one of /// `Pallet`, `Call`, `Storage`, `Event`, `Origin`, `Config`, `Inherent`, `ValidateUnsigned`. It /// is incompatible with `exclude_parts`. This specifies the part to use. In order to select a /// subset of the pallet parts. /// /// For example not using the part `Call` can be useful if the runtime doesn't want to make the /// pallet calls available. /// /// * `= $n` optional: number to define at which index the pallet variants in `OriginCaller`, `Call` /// and `Event` are encoded, and to define the ModuleToIndex value. /// /// if `= $n` is not given, then index is resolved in the same way as fieldless enum in Rust /// (i.e. incrementally from previous index): /// ```nocompile /// pallet1 .. = 2, /// pallet2 .., // Here pallet2 is given index 3 /// pallet3 .. = 0, /// pallet4 .., // Here pallet4 is given index 1 /// ``` /// /// # Note /// /// The population of the genesis storage depends on the order of pallets. So, if one of your /// pallets depends on another pallet, the pallet that is depended upon needs to come before /// the pallet depending on it. /// /// # Type definitions /// /// * The macro generates a type alias for each pallet to their `Pallet`. E.g. `type System = /// frame_system::Pallet` #[proc_macro] pub fn construct_runtime(input: TokenStream) -> TokenStream { construct_runtime::construct_runtime(input) } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet`. #[proc_macro_attribute] pub fn pallet(attr: TokenStream, item: TokenStream) -> TokenStream { pallet::pallet(attr, item) } /// An attribute macro that can be attached to a (non-empty) module declaration. Doing so will /// designate that module as a benchmarking module. /// /// See `frame_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn benchmarks(attr: TokenStream, tokens: TokenStream) -> TokenStream { match benchmark::benchmarks(attr, tokens, false) { Ok(tokens) => tokens, Err(err) => err.to_compile_error().into(), } } /// An attribute macro that can be attached to a (non-empty) module declaration. Doing so will /// designate that module as an instance benchmarking module. /// /// See `frame_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn instance_benchmarks(attr: TokenStream, tokens: TokenStream) -> TokenStream { match benchmark::benchmarks(attr, tokens, true) { Ok(tokens) => tokens, Err(err) => err.to_compile_error().into(), } } /// An attribute macro used to declare a benchmark within a benchmarking module. Must be /// attached to a function definition containing an `#[extrinsic_call]` or `#[block]` /// attribute. /// /// See `frame_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn benchmark(_attrs: TokenStream, _tokens: TokenStream) -> TokenStream { quote!(compile_error!( "`#[benchmark]` must be in a module labeled with #[benchmarks] or #[instance_benchmarks]." )) .into() } /// An attribute macro used to specify the extrinsic call inside a benchmark function, and also /// used as a boundary designating where the benchmark setup code ends, and the benchmark /// verification code begins. /// /// See `frame_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn extrinsic_call(_attrs: TokenStream, _tokens: TokenStream) -> TokenStream { quote!(compile_error!( "`#[extrinsic_call]` must be in a benchmark function definition labeled with `#[benchmark]`." );) .into() } /// An attribute macro used to specify that a block should be the measured portion of the /// enclosing benchmark function, This attribute is also used as a boundary designating where /// the benchmark setup code ends, and the benchmark verification code begins. /// /// See `frame_benchmarking::v2` for more info. #[proc_macro_attribute] pub fn block(_attrs: TokenStream, _tokens: TokenStream) -> TokenStream { quote!(compile_error!( "`#[block]` must be in a benchmark function definition labeled with `#[benchmark]`." )) .into() } /// Execute the annotated function in a new storage transaction. /// /// The return type of the annotated function must be `Result`. All changes to storage performed /// by the annotated function are discarded if it returns `Err`, or committed if `Ok`. /// /// # Example /// /// ```nocompile /// #[transactional] /// fn value_commits(v: u32) -> result::Result { /// Value::set(v); /// Ok(v) /// } /// /// #[transactional] /// fn value_rollbacks(v: u32) -> result::Result { /// Value::set(v); /// Err("nah") /// } /// ``` #[proc_macro_attribute] pub fn transactional(attr: TokenStream, input: TokenStream) -> TokenStream { transactional::transactional(attr, input).unwrap_or_else(|e| e.to_compile_error().into()) } /// /// --- /// /// Documentation for this macro can be found at `frame_support::require_transactional`. #[proc_macro_attribute] pub fn require_transactional(attr: TokenStream, input: TokenStream) -> TokenStream { transactional::require_transactional(attr, input) .unwrap_or_else(|e| e.to_compile_error().into()) } /// Derive [`Clone`] but do not bound any generic. /// /// Docs at `frame_support::CloneNoBound`. #[proc_macro_derive(CloneNoBound)] pub fn derive_clone_no_bound(input: TokenStream) -> TokenStream { no_bound::clone::derive_clone_no_bound(input) } /// Derive [`Debug`] but do not bound any generics. /// /// Docs at `frame_support::DebugNoBound`. #[proc_macro_derive(DebugNoBound)] pub fn derive_debug_no_bound(input: TokenStream) -> TokenStream { no_bound::debug::derive_debug_no_bound(input) } /// Derive [`Debug`], if `std` is enabled it uses `frame_support::DebugNoBound`, if `std` is not /// enabled it just returns `""`. /// This behaviour is useful to prevent bloating the runtime WASM blob from unneeded code. #[proc_macro_derive(RuntimeDebugNoBound)] pub fn derive_runtime_debug_no_bound(input: TokenStream) -> TokenStream { if cfg!(any(feature = "std", feature = "try-runtime")) { no_bound::debug::derive_debug_no_bound(input) } else { let input = syn::parse_macro_input!(input as syn::DeriveInput); let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); quote::quote!( const _: () = { impl #impl_generics ::core::fmt::Debug for #name #ty_generics #where_clause { fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> core::fmt::Result { fmt.write_str("") } } }; ) .into() } } /// Derive [`PartialEq`] but do not bound any generic. /// /// Docs at `frame_support::PartialEqNoBound`. #[proc_macro_derive(PartialEqNoBound)] pub fn derive_partial_eq_no_bound(input: TokenStream) -> TokenStream { no_bound::partial_eq::derive_partial_eq_no_bound(input) } /// DeriveEq but do no bound any generic. /// /// Docs at `frame_support::EqNoBound`. #[proc_macro_derive(EqNoBound)] pub fn derive_eq_no_bound(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); quote::quote_spanned!(name.span() => const _: () = { impl #impl_generics ::core::cmp::Eq for #name #ty_generics #where_clause {} }; ) .into() } /// Derive [`PartialOrd`] but do not bound any generic. Docs are at /// `frame_support::PartialOrdNoBound`. #[proc_macro_derive(PartialOrdNoBound)] pub fn derive_partial_ord_no_bound(input: TokenStream) -> TokenStream { no_bound::partial_ord::derive_partial_ord_no_bound(input) } /// Derive [`Ord`] but do no bound any generic. Docs are at `frame_support::OrdNoBound`. #[proc_macro_derive(OrdNoBound)] pub fn derive_ord_no_bound(input: TokenStream) -> TokenStream { no_bound::ord::derive_ord_no_bound(input) } /// derive `Default` but do no bound any generic. Docs are at `frame_support::DefaultNoBound`. #[proc_macro_derive(DefaultNoBound, attributes(default))] pub fn derive_default_no_bound(input: TokenStream) -> TokenStream { no_bound::default::derive_default_no_bound(input) } /// Macro used internally in FRAME to generate the crate version for a pallet. #[proc_macro] pub fn crate_to_crate_version(input: TokenStream) -> TokenStream { crate_version::crate_to_crate_version(input) .unwrap_or_else(|e| e.to_compile_error()) .into() } /// The number of module instances supported by the runtime, starting at index 1, /// and up to `NUMBER_OF_INSTANCE`. pub(crate) const NUMBER_OF_INSTANCE: u8 = 16; /// This macro is meant to be used by frame-support only. /// It implements the trait `HasKeyPrefix` and `HasReversibleKeyPrefix` for tuple of `Key`. #[proc_macro] pub fn impl_key_prefix_for_tuples(input: TokenStream) -> TokenStream { key_prefix::impl_key_prefix_for_tuples(input) .unwrap_or_else(syn::Error::into_compile_error) .into() } /// Internal macro use by frame_support to generate dummy part checker for old pallet declaration #[proc_macro] pub fn __generate_dummy_part_checker(input: TokenStream) -> TokenStream { dummy_part_checker::generate_dummy_part_checker(input) } /// Macro that inserts some tokens after the first match of some pattern. /// /// # Example: /// /// ```nocompile /// match_and_insert!( /// target = [{ Some content with { at some point match pattern } other match pattern are ignored }] /// pattern = [{ match pattern }] // the match pattern cannot contain any group: `[]`, `()`, `{}` /// // can relax this constraint, but will require modifying the match logic in code /// tokens = [{ expansion tokens }] // content inside braces can be anything including groups /// ); /// ``` /// /// will generate: /// /// ```nocompile /// Some content with { at some point match pattern expansion tokens } other match patterns are /// ignored /// ``` #[proc_macro] pub fn match_and_insert(input: TokenStream) -> TokenStream { match_and_insert::match_and_insert(input) } #[proc_macro_derive(PalletError, attributes(codec))] pub fn derive_pallet_error(input: TokenStream) -> TokenStream { pallet_error::derive_pallet_error(input) } /// Internal macro used by `frame_support` to create tt-call-compliant macros #[proc_macro] pub fn __create_tt_macro(input: TokenStream) -> TokenStream { tt_macro::create_tt_return_macro(input) } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::storage_alias`. #[proc_macro_attribute] pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream { storage_alias::storage_alias(attributes.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// This attribute can be used to derive a full implementation of a trait based on a local partial /// impl and an external impl containing defaults that can be overridden in the local impl. /// /// For a full end-to-end example, see [below](#use-case-auto-derive-test-pallet-config-traits). /// /// # Usage /// /// The attribute should be attached to an impl block (strictly speaking a `syn::ItemImpl`) for /// which we want to inject defaults in the event of missing trait items in the block. /// /// The attribute minimally takes a single `default_impl_path` argument, which should be the module /// path to an impl registered via [`#[register_default_impl]`](`macro@register_default_impl`) that /// contains the default trait items we want to potentially inject, with the general form: /// /// ```ignore /// #[derive_impl(default_impl_path)] /// impl SomeTrait for SomeStruct { /// ... /// } /// ``` /// /// Optionally, a `disambiguation_path` can be specified as follows by providing `as path::here` /// after the `default_impl_path`: /// /// ```ignore /// #[derive_impl(default_impl_path as disambiguation_path)] /// impl SomeTrait for SomeStruct { /// ... /// } /// ``` /// /// The `disambiguation_path`, if specified, should be the path to a trait that will be used to /// qualify all default entries that are injected into the local impl. For example if your /// `default_impl_path` is `some::path::TestTraitImpl` and your `disambiguation_path` is /// `another::path::DefaultTrait`, any items injected into the local impl will be qualified as /// `::specific_trait_item`. /// /// If you omit the `as disambiguation_path` portion, the `disambiguation_path` will internally /// default to `A` from the `impl A for B` part of the default impl. This is useful for scenarios /// where all of the relevant types are already in scope via `use` statements. /// /// In case the `default_impl_path` is scoped to a different module such as /// `some::path::TestTraitImpl`, the same scope is assumed for the `disambiguation_path`, i.e. /// `some::A`. This enables the use of `derive_impl` attribute without having to specify the /// `disambiguation_path` in most (if not all) uses within FRAME's context. /// /// Conversely, the `default_impl_path` argument is required and cannot be omitted. /// /// Optionally, `no_aggregated_types` can be specified as follows: /// /// ```ignore /// #[derive_impl(default_impl_path as disambiguation_path, no_aggregated_types)] /// impl SomeTrait for SomeStruct { /// ... /// } /// ``` /// /// If specified, this indicates that the aggregated types (as denoted by impl items /// attached with [`#[inject_runtime_type]`]) should not be injected with the respective concrete /// types. By default, all such types are injected. /// /// You can also make use of `#[pallet::no_default]` on specific items in your default impl that you /// want to ensure will not be copied over but that you nonetheless want to use locally in the /// context of the foreign impl and the pallet (or context) in which it is defined. /// /// ## Use-Case Example: Auto-Derive Test Pallet Config Traits /// /// The `#[derive_imp(..)]` attribute can be used to derive a test pallet `Config` based on an /// existing pallet `Config` that has been marked with /// [`#[pallet::config(with_default)]`](`macro@config`) (which under the hood, generates a /// `DefaultConfig` trait in the pallet in which the macro was invoked). /// /// In this case, the `#[derive_impl(..)]` attribute should be attached to an `impl` block that /// implements a compatible `Config` such as `frame_system::Config` for a test/mock runtime, and /// should receive as its first argument the path to a `DefaultConfig` impl that has been registered /// via [`#[register_default_impl]`](`macro@register_default_impl`), and as its second argument, the /// path to the auto-generated `DefaultConfig` for the existing pallet `Config` we want to base our /// test config off of. /// /// The following is what the `basic` example pallet would look like with a default testing config: /// /// ```ignore /// #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::pallet::DefaultConfig)] /// impl frame_system::Config for Test { /// // These are all defined by system as mandatory. /// type BaseCallFilter = frame_support::traits::Everything; /// type RuntimeEvent = RuntimeEvent; /// type RuntimeCall = RuntimeCall; /// type RuntimeOrigin = RuntimeOrigin; /// type OnSetCode = (); /// type PalletInfo = PalletInfo; /// type Block = Block; /// // We decide to override this one. /// type AccountData = pallet_balances::AccountData; /// } /// ``` /// /// where `TestDefaultConfig` was defined and registered as follows: /// ```ignore /// pub struct TestDefaultConfig; /// /// #[register_default_impl(TestDefaultConfig)] /// impl DefaultConfig for TestDefaultConfig { /// type Version = (); /// type BlockWeights = (); /// type BlockLength = (); /// type DbWeight = (); /// type Nonce = u64; /// type BlockNumber = u64; /// type Hash = sp_core::hash::H256; /// type Hashing = sp_runtime::traits::BlakeTwo256; /// type AccountId = AccountId; /// type Lookup = IdentityLookup; /// type BlockHashCount = frame_support::traits::ConstU64<10>; /// type AccountData = u32; /// type OnNewAccount = (); /// type OnKilledAccount = (); /// type SystemWeightInfo = (); /// type SS58Prefix = (); /// type MaxConsumers = frame_support::traits::ConstU32<16>; /// } /// ``` /// /// The above call to `derive_impl` would expand to roughly the following: /// ```ignore /// impl frame_system::Config for Test { /// use frame_system::config_preludes::TestDefaultConfig; /// use frame_system::pallet::DefaultConfig; /// /// type BaseCallFilter = frame_support::traits::Everything; /// type RuntimeEvent = RuntimeEvent; /// type RuntimeCall = RuntimeCall; /// type RuntimeOrigin = RuntimeOrigin; /// type OnSetCode = (); /// type PalletInfo = PalletInfo; /// type Block = Block; /// type AccountData = pallet_balances::AccountData; /// type Version = ::Version; /// type BlockWeights = ::BlockWeights; /// type BlockLength = ::BlockLength; /// type DbWeight = ::DbWeight; /// type Nonce = ::Nonce; /// type BlockNumber = ::BlockNumber; /// type Hash = ::Hash; /// type Hashing = ::Hashing; /// type AccountId = ::AccountId; /// type Lookup = ::Lookup; /// type BlockHashCount = ::BlockHashCount; /// type OnNewAccount = ::OnNewAccount; /// type OnKilledAccount = ::OnKilledAccount; /// type SystemWeightInfo = ::SystemWeightInfo; /// type SS58Prefix = ::SS58Prefix; /// type MaxConsumers = ::MaxConsumers; /// } /// ``` /// /// You can then use the resulting `Test` config in test scenarios. /// /// Note that items that are _not_ present in our local `DefaultConfig` are automatically copied /// from the foreign trait (in this case `TestDefaultConfig`) into the local trait impl (in this /// case `Test`), unless the trait item in the local trait impl is marked with /// [`#[pallet::no_default]`](`macro@no_default`), in which case it cannot be overridden, and any /// attempts to do so will result in a compiler error. /// /// See `frame/examples/default-config/tests.rs` for a runnable end-to-end example pallet that makes /// use of `derive_impl` to derive its testing config. /// /// See [here](`macro@config`) for more information and caveats about the auto-generated /// `DefaultConfig` trait. /// /// ## Optional Conventions /// /// Note that as an optional convention, we encourage creating a `config_preludes` module inside of /// your pallet. This is the convention we follow for `frame_system`'s `TestDefaultConfig` which, as /// shown above, is located at `frame_system::config_preludes::TestDefaultConfig`. This is just a /// suggested convention -- there is nothing in the code that expects modules with these names to be /// in place, so there is no imperative to follow this pattern unless desired. /// /// In `config_preludes`, you can place types named like: /// /// * `TestDefaultConfig` /// * `ParachainDefaultConfig` /// * `SolochainDefaultConfig` /// /// Signifying in which context they can be used. /// /// # Advanced Usage /// /// ## Expansion /// /// The `#[derive_impl(default_impl_path as disambiguation_path)]` attribute will expand to the /// local impl, with any extra items from the foreign impl that aren't present in the local impl /// also included. In the case of a colliding trait item, the version of the item that exists in the /// local impl will be retained. All imported items are qualified by the `disambiguation_path`, as /// discussed above. /// /// ## Handling of Unnamed Trait Items /// /// Items that lack a `syn::Ident` for whatever reason are first checked to see if they exist, /// verbatim, in the local/destination trait before they are copied over, so you should not need to /// worry about collisions between identical unnamed items. #[import_tokens_attr_verbatim { format!( "{}::macro_magic", match generate_access_from_frame_or_crate("frame-support") { Ok(path) => Ok(path), Err(_) => generate_access_from_frame_or_crate("polkadot-sdk-frame"), } .expect("Failed to find either `frame-support` or `polkadot-sdk-frame` in `Cargo.toml` dependencies.") .to_token_stream() .to_string() ) }] #[with_custom_parsing(derive_impl::DeriveImplAttrArgs)] #[proc_macro_attribute] pub fn derive_impl(attrs: TokenStream, input: TokenStream) -> TokenStream { let custom_attrs = parse_macro_input!(__custom_tokens as derive_impl::DeriveImplAttrArgs); derive_impl::derive_impl( __source_path.into(), attrs.into(), input.into(), custom_attrs.disambiguation_path, custom_attrs.no_aggregated_types, ) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::no_default`. #[proc_macro_attribute] pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::no_default_bounds`. #[proc_macro_attribute] pub fn no_default_bounds(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// Attach this attribute to an impl statement that you want to use with /// [`#[derive_impl(..)]`](`macro@derive_impl`). /// /// You must also provide an identifier/name as the attribute's argument. This is the name you /// must provide to [`#[derive_impl(..)]`](`macro@derive_impl`) when you import this impl via /// the `default_impl_path` argument. This name should be unique at the crate-level. /// /// ## Example /// /// ```ignore /// pub struct ExampleTestDefaultConfig; /// /// #[register_default_impl(ExampleTestDefaultConfig)] /// impl DefaultConfig for ExampleTestDefaultConfig { /// type Version = (); /// type BlockWeights = (); /// type BlockLength = (); /// ... /// type SS58Prefix = (); /// type MaxConsumers = frame_support::traits::ConstU32<16>; /// } /// ``` /// /// ## Advanced Usage /// /// This macro acts as a thin wrapper around macro_magic's `#[export_tokens]`. See the docs /// [here](https://docs.rs/macro_magic/latest/macro_magic/attr.export_tokens.html) for more /// info. /// /// There are some caveats when applying a `use` statement to bring a /// `#[register_default_impl]` item into scope. If you have a `#[register_default_impl]` /// defined in `my_crate::submodule::MyItem`, it is currently not sufficient to do something /// like: /// /// ```ignore /// use my_crate::submodule::MyItem; /// #[derive_impl(MyItem as Whatever)] /// ``` /// /// This will fail with a mysterious message about `__export_tokens_tt_my_item` not being /// defined. /// /// You can, however, do any of the following: /// ```ignore /// // partial path works /// use my_crate::submodule; /// #[derive_impl(submodule::MyItem as Whatever)] /// ``` /// ```ignore /// // full path works /// #[derive_impl(my_crate::submodule::MyItem as Whatever)] /// ``` /// ```ignore /// // wild-cards work /// use my_crate::submodule::*; /// #[derive_impl(MyItem as Whatever)] /// ``` #[proc_macro_attribute] pub fn register_default_impl(attrs: TokenStream, tokens: TokenStream) -> TokenStream { // ensure this is a impl statement let item_impl = syn::parse_macro_input!(tokens as ItemImpl); // internally wrap macro_magic's `#[export_tokens]` macro match macro_magic::mm_core::export_tokens_internal( attrs, item_impl.to_token_stream(), true, false, ) { Ok(tokens) => tokens.into(), Err(err) => err.to_compile_error().into(), } } /// /// --- /// /// Documentation for this macro can be found at /// `frame_support::pallet_prelude::inject_runtime_type`. #[proc_macro_attribute] pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { let item = tokens.clone(); let item = syn::parse_macro_input!(item as TraitItemType); if item.ident != "RuntimeCall" && item.ident != "RuntimeEvent" && item.ident != "RuntimeTask" && item.ident != "RuntimeOrigin" && item.ident != "RuntimeHoldReason" && item.ident != "RuntimeFreezeReason" && item.ident != "RuntimeParameters" && item.ident != "PalletInfo" { return syn::Error::new_spanned( item, "`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, \ `RuntimeTask`, `RuntimeOrigin`, `RuntimeParameters` or `PalletInfo`", ) .to_compile_error() .into() } tokens } /// Used internally to decorate pallet attribute macro stubs when they are erroneously used /// outside of a pallet module fn pallet_macro_stub() -> TokenStream { quote!(compile_error!( "This attribute can only be used from within a pallet module marked with `#[frame_support::pallet]`" )) .into() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::config`. #[proc_macro_attribute] pub fn config(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::constant`. #[proc_macro_attribute] pub fn constant(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::constant_name`. #[proc_macro_attribute] pub fn constant_name(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `frame_support::pallet_macros::disable_frame_system_supertrait_check`. #[proc_macro_attribute] pub fn disable_frame_system_supertrait_check(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::storage_version`. #[proc_macro_attribute] pub fn storage_version(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::hooks`. #[proc_macro_attribute] pub fn hooks(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::weight`. #[proc_macro_attribute] pub fn weight(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::compact`. #[proc_macro_attribute] pub fn compact(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::call`. #[proc_macro_attribute] pub fn call(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// Each dispatchable may also be annotated with the `#[pallet::call_index($idx)]` attribute, /// which explicitly defines the codec index for the dispatchable function in the `Call` enum. /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::call_index`. #[proc_macro_attribute] pub fn call_index(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::feeless_if`. #[proc_macro_attribute] pub fn feeless_if(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::extra_constants`. #[proc_macro_attribute] pub fn extra_constants(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::error`. #[proc_macro_attribute] pub fn error(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::event`. #[proc_macro_attribute] pub fn event(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::generate_deposit`. #[proc_macro_attribute] pub fn generate_deposit(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::storage`. #[proc_macro_attribute] pub fn storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::getter`. #[proc_macro_attribute] pub fn getter(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::storage_prefix`. #[proc_macro_attribute] pub fn storage_prefix(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::unbounded`. #[proc_macro_attribute] pub fn unbounded(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::whitelist_storage`. #[proc_macro_attribute] pub fn whitelist_storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at /// `frame_support::pallet_macros::disable_try_decode_storage`. #[proc_macro_attribute] pub fn disable_try_decode_storage(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::type_value`. #[proc_macro_attribute] pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::genesis_config`. #[proc_macro_attribute] pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::genesis_build`. #[proc_macro_attribute] pub fn genesis_build(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::inherent`. #[proc_macro_attribute] pub fn inherent(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::validate_unsigned`. #[proc_macro_attribute] pub fn validate_unsigned(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::origin`. #[proc_macro_attribute] pub fn origin(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// Documentation for this macro can be found at `frame_support::pallet_macros::composite_enum`. #[proc_macro_attribute] pub fn composite_enum(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::tasks_experimental`. #[proc_macro_attribute] pub fn tasks_experimental(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::task_list`. #[proc_macro_attribute] pub fn task_list(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::task_condition`. #[proc_macro_attribute] pub fn task_condition(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::task_weight`. #[proc_macro_attribute] pub fn task_weight(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::task_index`. #[proc_macro_attribute] pub fn task_index(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::pallet_section`. #[proc_macro_attribute] pub fn pallet_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { let tokens_clone = tokens.clone(); // ensure this can only be attached to a module let _mod = parse_macro_input!(tokens_clone as ItemMod); // use macro_magic's export_tokens as the internal implementation otherwise match macro_magic::mm_core::export_tokens_internal(attr, tokens, false, true) { Ok(tokens) => tokens.into(), Err(err) => err.to_compile_error().into(), } } /// /// --- /// /// **Rust-Analyzer users**: See the documentation of the Rust item in /// `frame_support::pallet_macros::import_section`. #[import_tokens_attr { format!( "{}::macro_magic", match generate_access_from_frame_or_crate("frame-support") { Ok(path) => Ok(path), Err(_) => generate_access_from_frame_or_crate("polkadot-sdk-frame"), } .expect("Failed to find either `frame-support` or `polkadot-sdk-frame` in `Cargo.toml` dependencies.") .to_token_stream() .to_string() ) }] #[proc_macro_attribute] pub fn import_section(attr: TokenStream, tokens: TokenStream) -> TokenStream { let foreign_mod = parse_macro_input!(attr as ItemMod); let mut internal_mod = parse_macro_input!(tokens as ItemMod); // check that internal_mod is a pallet module if !internal_mod.attrs.iter().any(|attr| { if let Some(last_seg) = attr.path().segments.last() { last_seg.ident == "pallet" } else { false } }) { return Error::new( internal_mod.ident.span(), "`#[import_section]` can only be applied to a valid pallet module", ) .to_compile_error() .into() } if let Some(ref mut content) = internal_mod.content { if let Some(foreign_content) = foreign_mod.content { content.1.extend(foreign_content.1); } } quote! { #internal_mod } .into() } /// Construct a runtime, with the given name and the given pallets. /// /// # Example: /// /// ```ignore /// #[frame_support::runtime] /// mod runtime { /// // The main runtime /// #[runtime::runtime] /// // Runtime Types to be generated /// #[runtime::derive( /// RuntimeCall, /// RuntimeEvent, /// RuntimeError, /// RuntimeOrigin, /// RuntimeFreezeReason, /// RuntimeHoldReason, /// RuntimeSlashReason, /// RuntimeLockId, /// RuntimeTask, /// )] /// pub struct Runtime; /// /// #[runtime::pallet_index(0)] /// pub type System = frame_system; /// /// #[runtime::pallet_index(1)] /// pub type Test = path::to::test; /// /// // Pallet with instance. /// #[runtime::pallet_index(2)] /// pub type Test2_Instance1 = test2; /// /// // Pallet with calls disabled. /// #[runtime::pallet_index(3)] /// #[runtime::disable_call] /// pub type Test3 = test3; /// /// // Pallet with unsigned extrinsics disabled. /// #[runtime::pallet_index(4)] /// #[runtime::disable_unsigned] /// pub type Test4 = test4; /// } /// ``` /// /// # Legacy Ordering /// /// An optional attribute can be defined as #[frame_support::runtime(legacy_ordering)] to /// ensure that the order of hooks is same as the order of pallets (and not based on the /// pallet_index). This is to support legacy runtimes and should be avoided for new ones. /// /// # Note /// /// The population of the genesis storage depends on the order of pallets. So, if one of your /// pallets depends on another pallet, the pallet that is depended upon needs to come before /// the pallet depending on it. /// /// # Type definitions /// /// * The macro generates a type alias for each pallet to their `Pallet`. E.g. `type System = /// frame_system::Pallet` #[cfg(feature = "experimental")] #[proc_macro_attribute] pub fn runtime(attr: TokenStream, item: TokenStream) -> TokenStream { runtime::runtime(attr, item) } /// Mark a module that contains dynamic parameters. /// /// See the `pallet_parameters` for a full example. /// /// # Arguments /// /// The macro accepts two positional arguments, of which the second is optional. /// /// ## Aggregated Enum Name /// /// This sets the name that the aggregated Key-Value enum will be named after. Common names would be /// `RuntimeParameters`, akin to `RuntimeCall`, `RuntimeOrigin` etc. There is no default value for /// this argument. /// /// ## Parameter Storage Backend /// /// The second argument provides access to the storage of the parameters. It can either be set on /// on this attribute, or on the inner ones. If set on both, the inner one takes precedence. #[proc_macro_attribute] pub fn dynamic_params(attrs: TokenStream, input: TokenStream) -> TokenStream { dynamic_params::dynamic_params(attrs.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// Define a module inside a [`macro@dynamic_params`] module that contains dynamic parameters. /// /// See the `pallet_parameters` for a full example. /// /// # Argument /// /// This attribute takes one optional argument. The argument can either be put here or on the /// surrounding `#[dynamic_params]` attribute. If set on both, the inner one takes precedence. #[proc_macro_attribute] pub fn dynamic_pallet_params(attrs: TokenStream, input: TokenStream) -> TokenStream { dynamic_params::dynamic_pallet_params(attrs.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() } /// Used internally by [`dynamic_params`]. #[doc(hidden)] #[proc_macro_attribute] pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream) -> TokenStream { dynamic_params::dynamic_aggregated_params_internal(attrs.into(), input.into()) .unwrap_or_else(|r| r.into_compile_error()) .into() }