Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frame/support/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primi
sp-arithmetic = { version = "4.0.0-dev", default-features = false, path = "../../primitives/arithmetic" }
sp-inherents = { version = "4.0.0-dev", default-features = false, path = "../../primitives/inherents" }
sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" }
tt-call = "1.0.8"
frame-support-procedural = { version = "4.0.0-dev", default-features = false, path = "./procedural" }
paste = "1.0"
once_cell = { version = "1", default-features = false, optional = true }
Expand Down
37 changes: 9 additions & 28 deletions frame/support/procedural/src/construct_runtime/expand/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,21 @@ pub fn expand_outer_config(
let mut query_genesis_config_part_macros = Vec::new();

for decl in pallet_decls {
if let Some(pallet_entry) = decl.find_part("Config") {
if decl.exists_part("Config") {
let path = &decl.path;
let pallet_name = &decl.name;
let path_str = path.into_token_stream().to_string();
let config = format_ident!("{}Config", pallet_name);
let config = &format_ident!("{}Config", pallet_name);
let field_name =
&Ident::new(&pallet_name.to_string().to_snake_case(), decl.name.span());
let part_is_generic = !pallet_entry.generics.params.is_empty();
let instance = decl.instance.as_ref().into_iter();

types.extend(expand_config_types(runtime, decl, &config, part_is_generic));
types.extend(quote! {
#[cfg(any(feature = "std", test))]
pub type #config = <
#path::Pallet<#runtime #(, #path::#instance)*> as #path::SubstratePalletConfig
>::GenesisConfig;
});
fields.extend(quote!(pub #field_name: #config,));
build_storage_calls.extend(expand_config_build_storage_call(
scrate,
Expand Down Expand Up @@ -91,30 +96,6 @@ pub fn expand_outer_config(
}
}

fn expand_config_types(
runtime: &Ident,
decl: &Pallet,
config: &Ident,
part_is_generic: bool,
) -> TokenStream {
let path = &decl.path;

match (decl.instance.as_ref(), part_is_generic) {
(Some(inst), true) => quote! {
#[cfg(any(feature = "std", test))]
pub type #config = #path::GenesisConfig<#runtime, #path::#inst>;
},
(None, true) => quote! {
#[cfg(any(feature = "std", test))]
pub type #config = #path::GenesisConfig<#runtime>;
},
(_, false) => quote! {
#[cfg(any(feature = "std", test))]
pub type #config = #path::GenesisConfig;
},
}
}

fn expand_config_build_storage_call(
scrate: &TokenStream,
runtime: &Ident,
Expand Down
68 changes: 14 additions & 54 deletions frame/support/procedural/src/construct_runtime/expand/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
// See the License for the specific language governing permissions and
// limitations under the License

use crate::construct_runtime::Pallet;
use crate::construct_runtime::{Pallet, SYSTEM_PALLET_NAME};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Generics, Ident};
use syn::Ident;

pub fn expand_outer_event(
runtime: &Ident,
Expand All @@ -30,37 +30,24 @@ pub fn expand_outer_event(
let mut query_event_part_macros = Vec::new();

for pallet_decl in pallet_decls {
if let Some(pallet_entry) = pallet_decl.find_part("Event") {
if pallet_decl.exists_part("Event") {
let path = &pallet_decl.path;
let pallet_name = &pallet_decl.name;
let index = pallet_decl.index;
let instance = pallet_decl.instance.as_ref();
let generics = &pallet_entry.generics;

if instance.is_some() && generics.params.is_empty() {
let msg = format!(
"Instantiable pallet with no generic `Event` cannot \
be constructed: pallet `{}` must have generic `Event`",
pallet_name,
);
return Err(syn::Error::new(pallet_name.span(), msg))
}

let part_is_generic = !generics.params.is_empty();
let pallet_event = match (instance, part_is_generic) {
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
(None, true) => quote!(#path::Event::<#runtime>),
(None, false) => quote!(#path::Event),
let pallet_event = if pallet_decl.name == SYSTEM_PALLET_NAME {
// Note: for some reason, the compiler recognizes
// `<frame_system::Pallet<Runtime> as frame_system::SubstratePalletEvent>::Event` as
// essentially the same as the outer/runtime Event type, which then causes an error
// about conflicting implementations of the From<Event> trait for the Event type,
// and thereby necessitating a special case for the system pallet.
quote!(#path::Event<#runtime>)
} else {
let instance = pallet_decl.instance.as_ref().into_iter();
quote!(<#path::Pallet<#runtime #(, #path::#instance)*> as #path::SubstratePalletEvent>::Event)
};

event_variants.extend(expand_event_variant(
runtime,
pallet_decl,
index,
instance,
generics,
));
event_variants.extend(quote!(#[codec(index = #index)] #pallet_name(#pallet_event),));
event_conversions.extend(expand_event_conversion(scrate, pallet_decl, &pallet_event));
query_event_part_macros.push(quote! {
#path::__substrate_event_check::is_event_part_defined!(#pallet_name);
Expand All @@ -87,33 +74,6 @@ pub fn expand_outer_event(
})
}

fn expand_event_variant(
runtime: &Ident,
pallet: &Pallet,
index: u8,
instance: Option<&Ident>,
generics: &Generics,
) -> TokenStream {
let path = &pallet.path;
let variant_name = &pallet.name;
let part_is_generic = !generics.params.is_empty();

match instance {
Some(inst) if part_is_generic => {
quote!(#[codec(index = #index)] #variant_name(#path::Event<#runtime, #path::#inst>),)
},
Some(inst) => {
quote!(#[codec(index = #index)] #variant_name(#path::Event<#path::#inst>),)
},
None if part_is_generic => {
quote!(#[codec(index = #index)] #variant_name(#path::Event<#runtime>),)
},
None => {
quote!(#[codec(index = #index)] #variant_name(#path::Event),)
},
}
}

fn expand_event_conversion(
scrate: &TokenStream,
pallet: &Pallet,
Expand Down
23 changes: 11 additions & 12 deletions frame/support/procedural/src/construct_runtime/expand/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License

use crate::construct_runtime::Pallet;
use crate::construct_runtime::{Pallet, SYSTEM_PALLET_NAME};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Ident, TypePath};
Expand Down Expand Up @@ -132,17 +132,16 @@ fn expand_pallet_metadata_events(
) -> TokenStream {
if filtered_names.contains(&"Event") {
let path = &decl.path;
let part_is_generic = !decl
.find_part("Event")
.expect("Event part exists; qed")
.generics
.params
.is_empty();
let pallet_event = match (decl.instance.as_ref(), part_is_generic) {
(Some(inst), true) => quote!(#path::Event::<#runtime, #path::#inst>),
(Some(inst), false) => quote!(#path::Event::<#path::#inst>),
(None, true) => quote!(#path::Event::<#runtime>),
(None, false) => quote!(#path::Event),
let pallet_event = if decl.name == SYSTEM_PALLET_NAME {
// Note: for some reason, the compiler recognizes
// `<frame_system::Pallet<Runtime> as frame_system::SubstratePalletEvent>::Event` as
// essentially the same as the outer/runtime Event type, which then causes an error
// about conflicting implementations of the From<Event> trait for the Event type, and
// thereby necessitating a special case for the system pallet.
quote!(#path::Event<#runtime>)
} else {
let instance = decl.instance.as_ref().into_iter();
quote!(<#path::Pallet<#runtime #(, #path::#instance)*> as #path::SubstratePalletEvent>::Event)
};

quote! {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn expand_outer_origin(
syn::Error::new(
pallets_token.span,
"`System` pallet declaration is missing. \
Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event},`",
)
})?;

Expand Down
20 changes: 13 additions & 7 deletions frame/support/procedural/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mod pallet;
mod partial_eq_no_bound;
mod storage;
mod transactional;
mod tt_macro;

use proc_macro::TokenStream;
use std::{cell::RefCell, str::FromStr};
Expand Down Expand Up @@ -229,7 +230,7 @@ fn get_cargo_env_var<T: FromStr>(version_env: &str) -> std::result::Result<T, ()
/// construct_runtime!(
/// pub enum Runtime with ... {
/// ...,
/// Example: example::{Pallet, Storage, ..., Config<T>},
/// Example: example::{Pallet, Storage, ..., Config},
/// ...,
/// }
/// );
Expand Down Expand Up @@ -304,13 +305,13 @@ pub fn decl_storage(input: TokenStream) -> TokenStream {
/// NodeBlock = node::Block,
/// UncheckedExtrinsic = UncheckedExtrinsic
/// {
/// System: system::{Pallet, Call, Event<T>, Config<T>} = 0,
/// System: system::{Pallet, Call, Event, Config} = 0,
/// Test: test::{Pallet, Call} = 1,
/// Test2: test_with_long_module::{Pallet, Event<T>},
/// Test2: test_with_long_module::{Pallet, Event},
///
/// // Pallets with instances
/// Test3_Instance1: test3::<Instance1>::{Pallet, Call, Storage, Event<T, I>, Config<T, I>, Origin<T, I>},
/// Test3_DefaultInstance: test3::{Pallet, Call, Storage, Event<T>, Config<T>, Origin<T>} = 4,
/// Test3_DefaultInstance: test3::{Pallet, Call, Storage, Event, Config, Origin<T>} = 4,
/// }
/// )
/// ```
Expand All @@ -325,10 +326,9 @@ pub fn decl_storage(input: TokenStream) -> TokenStream {
/// - `Pallet` - Required for all pallets
/// - `Call` - If the pallet has callable functions
/// - `Storage` - If the pallet uses storage
/// - `Event` or `Event<T>` (if the event is generic) - If the pallet emits events
/// - `Event` - If the pallet emits events
/// - `Origin` or `Origin<T>` (if the origin is generic) - If the pallet has instanciable origins
/// - `Config` or `Config<T>` (if the config is generic) - If the pallet builds the genesis storage
/// with `GenesisConfig`
/// - `Config` - If the pallet builds the genesis storage with `GenesisConfig`
/// - `Inherent` - If the pallet provides/can check inherents.
/// - `ValidateUnsigned` - If the pallet validates unsigned extrinsics.
///
Expand Down Expand Up @@ -498,3 +498,9 @@ pub fn impl_key_prefix_for_tuples(input: TokenStream) -> TokenStream {
pub fn __generate_dummy_part_checker(input: TokenStream) -> TokenStream {
dummy_part_checker::generate_dummy_part_checker(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)
}
13 changes: 11 additions & 2 deletions frame/support/procedural/src/pallet/expand/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,12 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
#[scale_info(skip_type_params(#event_use_gen), capture_docs = "always")]
));

let type_impl_gen = &def.type_impl_generics(event.attr_span);
let type_use_gen = &def.type_use_generics(event.attr_span);

let deposit_event = if let Some(deposit_event) = &event.deposit_event {
let event_use_gen = &event.gen_kind.type_use_gen(event.attr_span);
let trait_use_gen = &def.trait_use_generics(event.attr_span);
let type_impl_gen = &def.type_impl_generics(event.attr_span);
let type_use_gen = &def.type_use_generics(event.attr_span);

let PalletEventDepositAttr { fn_vis, fn_span, .. } = deposit_event;

Expand Down Expand Up @@ -164,6 +165,14 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
pub use #macro_ident as is_event_part_defined;
}

pub trait SubstratePalletEvent {
type Event;
}

impl<#type_impl_gen> SubstratePalletEvent for Pallet<#type_use_gen> #completed_where_clause {
type Event = #event_ident<#event_use_gen>;
}

#deposit_event

impl<#event_impl_gen> From<#event_ident<#event_use_gen>> for () #event_where_clause {
Expand Down
15 changes: 15 additions & 0 deletions frame/support/procedural/src/pallet/expand/genesis_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,22 @@ pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream {
_ => unreachable!("Checked by genesis_config parser"),
}

let config_ident = &genesis_config.genesis_config;
let config_use_gen = &genesis_config.gen_kind.type_use_gen(config_ident.span());
let config_where_clause = def.config.where_clause.iter();
let type_impl_gen = &def.type_impl_generics(config_ident.span());
let type_use_gen = &def.type_use_generics(config_ident.span());

quote::quote! {
pub trait SubstratePalletConfig {
type GenesisConfig;
}

#[cfg(feature = "std")]
impl<#type_impl_gen> SubstratePalletConfig for Pallet<#type_use_gen> #(#config_where_clause)* {
type GenesisConfig = #config_ident<#config_use_gen>;
}

#[doc(hidden)]
pub mod __substrate_genesis_config_check {
#[macro_export]
Expand Down
2 changes: 1 addition & 1 deletion frame/support/procedural/src/pallet/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ impl GenericKind {

/// Return the generic to be used when using the type.
///
/// Depending on its definition it can be: ``, `T` or `T, I`
/// Depending on its definition it can be: ` `, `T` or `T, I`
pub fn type_use_gen(&self, span: proc_macro2::Span) -> proc_macro2::TokenStream {
match self {
GenericKind::None => quote::quote!(),
Expand Down
25 changes: 25 additions & 0 deletions frame/support/procedural/src/storage/genesis_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,31 @@ fn decl_genesis_config_and_impl_default(
}
}
}

macro_rules! impl_substrate_pallet_config {
{
pallet = [{ $pallet_type:ident <$config_instance:ident : $config_name:ident $(<I>, $instance:ident : $instantiable:path)?> }]
where_bounds = [{ $( $other_where_bounds:tt )* }]
} => {
pub trait SubstratePalletConfig {
type GenesisConfig;
}

#[cfg(feature = "std")]
impl<$config_instance: $config_name $(<I>, $instance: $instantiable)?> SubstratePalletConfig
for $pallet_type<$config_instance $(, $instance)?>
where
$( $other_where_bounds )*
{
type GenesisConfig = GenesisConfig#genesis_struct;
}
};
}

#scrate::tt_call! {
macro = [{ tt_get_pallet_type }]
~~> impl_substrate_pallet_config
}
)
}

Expand Down
Loading