Macros to use path instead of ident (#1474)

This commit is contained in:
Juan
2023-10-14 08:26:19 +02:00
committed by GitHub
parent 1f28cddd6f
commit 7c87d61f5a
26 changed files with 489 additions and 134 deletions
Generated
+17
View File
@@ -5098,6 +5098,14 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
[[package]]
name = "frame"
version = "0.1.0"
dependencies = [
"frame-support",
"frame-system",
]
[[package]]
name = "frame-benchmarking"
version = "4.0.0-dev"
@@ -5426,6 +5434,15 @@ dependencies = [
"sp-runtime",
]
[[package]]
name = "frame-support-test-stg-frame-crate"
version = "0.1.0"
dependencies = [
"frame",
"parity-scale-codec",
"scale-info",
]
[[package]]
name = "frame-system"
version = "4.0.0-dev"
+2
View File
@@ -345,6 +345,8 @@ members = [
"substrate/frame/support/test",
"substrate/frame/support/test/compile_pass",
"substrate/frame/support/test/pallet",
"substrate/frame/support/test/stg_frame_crate/frame",
"substrate/frame/support/test/stg_frame_crate",
"substrate/frame/system",
"substrate/frame/system/benchmarking",
"substrate/frame/system/rpc/runtime-api",
@@ -18,7 +18,7 @@
//! Home of the parsing and expansion code for the new pallet benchmarking syntax
use derive_syn_parse::Parse;
use frame_support_procedural_tools::generate_crate_access_2018;
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens};
@@ -418,7 +418,8 @@ pub fn benchmarks(
true => quote!(T: Config<I>, I: 'static),
};
let krate = generate_crate_access_2018("frame-benchmarking")?;
let krate = generate_access_from_frame_or_crate("frame-benchmarking")?;
let frame_system = generate_access_from_frame_or_crate("frame-system")?;
// benchmark name variables
let benchmark_names_str: Vec<String> = benchmark_names.iter().map(|n| n.to_string()).collect();
@@ -488,7 +489,7 @@ pub fn benchmarks(
}
#[cfg(any(feature = "runtime-benchmarks", test))]
impl<#type_impl_generics> #krate::Benchmarking for Pallet<#type_use_generics>
where T: frame_system::Config, #where_clause
where T: #frame_system::Config, #where_clause
{
fn benchmarks(
extra: bool,
@@ -535,7 +536,7 @@ pub fn benchmarks(
_ => return Err("Could not find extrinsic.".into()),
};
let mut whitelist = whitelist.to_vec();
let whitelisted_caller_key = <frame_system::Account<
let whitelisted_caller_key = <#frame_system::Account<
T,
> as #krate::__private::storage::StorageMap<_, _,>>::hashed_key_for(
#krate::whitelisted_caller::<T::AccountId>()
@@ -571,8 +572,8 @@ pub fn benchmarks(
>::instance(&selected_benchmark, c, verify)?;
// Set the block number to at least 1 so events are deposited.
if #krate::__private::Zero::is_zero(&frame_system::Pallet::<T>::block_number()) {
frame_system::Pallet::<T>::set_block_number(1u32.into());
if #krate::__private::Zero::is_zero(&#frame_system::Pallet::<T>::block_number()) {
#frame_system::Pallet::<T>::set_block_number(1u32.into());
}
// Commit the externalities to the database, flushing the DB cache.
@@ -654,7 +655,7 @@ pub fn benchmarks(
}
#[cfg(test)]
impl<#type_impl_generics> Pallet<#type_use_generics> where T: ::frame_system::Config, #where_clause {
impl<#type_impl_generics> Pallet<#type_use_generics> where T: #frame_system::Config, #where_clause {
/// Test a particular benchmark by name.
///
/// This isn't called `test_benchmark_by_name` just in case some end-user eventually
@@ -719,10 +720,14 @@ fn expand_benchmark(
where_clause: TokenStream2,
) -> TokenStream2 {
// set up variables needed during quoting
let krate = match generate_crate_access_2018("frame-benchmarking") {
let krate = match generate_access_from_frame_or_crate("frame-benchmarking") {
Ok(ident) => ident,
Err(err) => return err.to_compile_error().into(),
};
let frame_system = match generate_access_from_frame_or_crate("frame-system") {
Ok(path) => path,
Err(err) => return err.to_compile_error().into(),
};
let codec = quote!(#krate::__private::codec);
let traits = quote!(#krate::__private::traits);
let setup_stmts = benchmark_def.setup_stmts;
@@ -762,7 +767,7 @@ fn expand_benchmark(
Expr::Cast(t) => {
let ty = t.ty.clone();
quote! {
<<T as frame_system::Config>::RuntimeOrigin as From<#ty>>::from(#origin);
<<T as #frame_system::Config>::RuntimeOrigin as From<#ty>>::from(#origin);
}
},
_ => quote! {
@@ -932,7 +937,7 @@ fn expand_benchmark(
}
#[cfg(test)]
impl<#type_impl_generics> Pallet<#type_use_generics> where T: ::frame_system::Config, #where_clause {
impl<#type_impl_generics> Pallet<#type_use_generics> where T: #frame_system::Config, #where_clause {
#[allow(unused)]
fn #test_ident() -> Result<(), #krate::BenchmarkError> {
let selected_benchmark = SelectedBenchmark::#name;
@@ -951,8 +956,8 @@ fn expand_benchmark(
>::instance(&selected_benchmark, &c, true)?;
// Set the block number to at least 1 so events are deposited.
if #krate::__private::Zero::is_zero(&frame_system::Pallet::<T>::block_number()) {
frame_system::Pallet::<T>::set_block_number(1u32.into());
if #krate::__private::Zero::is_zero(&#frame_system::Pallet::<T>::block_number()) {
#frame_system::Pallet::<T>::set_block_number(1u32.into());
}
// Run execution + verification
@@ -214,7 +214,7 @@ mod parse;
use crate::pallet::parse::helper::two128_str;
use cfg_expr::Predicate;
use frame_support_procedural_tools::{
generate_crate_access, generate_crate_access_2018, generate_hidden_includes,
generate_access_from_frame_or_crate, generate_crate_access, generate_hidden_includes,
};
use itertools::Itertools;
use parse::{ExplicitRuntimeDeclaration, ImplicitRuntimeDeclaration, Pallet, RuntimeDeclaration};
@@ -272,7 +272,7 @@ fn construct_runtime_implicit_to_explicit(
input: TokenStream2,
definition: ImplicitRuntimeDeclaration,
) -> Result<TokenStream2> {
let frame_support = generate_crate_access_2018("frame-support")?;
let frame_support = generate_access_from_frame_or_crate("frame-support")?;
let mut expansion = quote::quote!(
#frame_support::construct_runtime! { #input }
);
@@ -283,7 +283,7 @@ fn construct_runtime_implicit_to_explicit(
expansion = quote::quote!(
#frame_support::__private::tt_call! {
macro = [{ #pallet_path::tt_default_parts }]
frame_support = [{ #frame_support }]
your_tt_return = [{ #frame_support::__private::tt_return }]
~~> #frame_support::match_and_insert! {
target = [{ #expansion }]
pattern = [{ #pallet_name: #pallet_path #pallet_instance }]
@@ -308,7 +308,7 @@ fn construct_runtime_explicit_to_explicit_expanded(
input: TokenStream2,
definition: ExplicitRuntimeDeclaration,
) -> Result<TokenStream2> {
let frame_support = generate_crate_access_2018("frame-support")?;
let frame_support = generate_access_from_frame_or_crate("frame-support")?;
let mut expansion = quote::quote!(
#frame_support::construct_runtime! { #input }
);
@@ -319,7 +319,7 @@ fn construct_runtime_explicit_to_explicit_expanded(
expansion = quote::quote!(
#frame_support::__private::tt_call! {
macro = [{ #pallet_path::tt_extra_parts }]
frame_support = [{ #frame_support }]
your_tt_return = [{ #frame_support::__private::tt_return }]
~~> #frame_support::match_and_insert! {
target = [{ #expansion }]
pattern = [{ #pallet_name: #pallet_path #pallet_instance }]
@@ -372,7 +372,7 @@ fn construct_runtime_final_expansion(
let scrate = generate_crate_access(hidden_crate_name, "frame-support");
let scrate_decl = generate_hidden_includes(hidden_crate_name, "frame-support");
let frame_system = generate_crate_access_2018("frame-system")?;
let frame_system = generate_access_from_frame_or_crate("frame-system")?;
let block = quote!(<#name as #frame_system::Config>::Block);
let unchecked_extrinsic = quote!(<#block as #scrate::sp_runtime::traits::Block>::Extrinsic);
@@ -799,7 +799,7 @@ fn decl_static_assertions(
quote! {
#scrate::__private::tt_call! {
macro = [{ #path::tt_error_token }]
frame_support = [{ #scrate }]
your_tt_return = [{ #scrate::__private::tt_return }]
~~> #scrate::assert_error_encoded_size! {
path = [{ #path }]
runtime = [{ #runtime }]
@@ -18,7 +18,7 @@
//! Implementation of macros related to crate versioning.
use super::get_cargo_env_var;
use frame_support_procedural_tools::generate_crate_access_2018;
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use proc_macro2::{Span, TokenStream};
use syn::{Error, Result};
@@ -42,7 +42,7 @@ pub fn crate_to_crate_version(input: proc_macro::TokenStream) -> Result<TokenStr
let patch_version = get_cargo_env_var::<u8>("CARGO_PKG_VERSION_PATCH")
.map_err(|_| create_error("Patch version needs to fit into `u8`"))?;
let crate_ = generate_crate_access_2018("frame-support")?;
let crate_ = generate_access_from_frame_or_crate("frame-support")?;
Ok(quote::quote! {
#crate_::traits::CrateVersion {
@@ -15,6 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, ToTokens};
use syn::{Ident, Result};
@@ -27,6 +28,7 @@ pub fn impl_key_prefix_for_tuples(input: proc_macro::TokenStream) -> Result<Toke
}
let mut all_trait_impls = TokenStream::new();
let frame_support = generate_access_from_frame_or_crate("frame-support")?;
for i in 2..=MAX_IDENTS {
let current_tuple = (0..i)
@@ -64,7 +66,10 @@ pub fn impl_key_prefix_for_tuples(input: proc_macro::TokenStream) -> Result<Toke
#(#hashers: ReversibleStorageHasher,)*
#(#kargs: EncodeLike<#prefixes>),*
> HasReversibleKeyPrefix<( #( #kargs, )* )> for ( #( Key<#hashers, #current_tuple>, )* ) {
fn decode_partial_key(key_material: &[u8]) -> Result<Self::Suffix, codec::Error> {
fn decode_partial_key(key_material: &[u8]) -> Result<
Self::Suffix,
#frame_support::__private::codec::Error,
> {
<#suffix_keygen>::decode_final_key(key_material).map(|k| k.0)
}
}
@@ -33,7 +33,7 @@ mod storage_alias;
mod transactional;
mod tt_macro;
use frame_support_procedural_tools::generate_crate_access_2018;
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};
@@ -754,9 +754,9 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream
#[import_tokens_attr_verbatim {
format!(
"{}::macro_magic",
match generate_crate_access_2018("frame-support") {
match generate_access_from_frame_or_crate("frame-support") {
Ok(path) => Ok(path),
Err(_) => generate_crate_access_2018("frame"),
Err(_) => generate_access_from_frame_or_crate("frame"),
}
.expect("Failed to find either `frame-support` or `frame` in `Cargo.toml` dependencies.")
.to_token_stream()
@@ -1612,9 +1612,9 @@ pub fn pallet_section(attr: TokenStream, tokens: TokenStream) -> TokenStream {
#[import_tokens_attr {
format!(
"{}::macro_magic",
match generate_crate_access_2018("frame-support") {
match generate_access_from_frame_or_crate("frame-support") {
Ok(path) => Ok(path),
Err(_) => generate_crate_access_2018("frame"),
Err(_) => generate_access_from_frame_or_crate("frame"),
}
.expect("Failed to find either `frame-support` or `frame` in `Cargo.toml` dependencies.")
.to_token_stream()
@@ -42,9 +42,9 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
macro_rules! #error_token_unique_id {
{
$caller:tt
frame_support = [{ $($frame_support:ident)::* }]
your_tt_return = [{ $my_tt_return:path }]
} => {
$($frame_support::)*__private::tt_return! {
$my_tt_return! {
$caller
}
};
@@ -170,9 +170,9 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
macro_rules! #error_token_unique_id {
{
$caller:tt
frame_support = [{ $($frame_support:ident)::* }]
your_tt_return = [{ $my_tt_return:path }]
} => {
$($frame_support::)*__private::tt_return! {
$my_tt_return! {
$caller
error = [{ #error_ident }]
}
@@ -17,6 +17,7 @@
use crate::{pallet::Def, COUNTER};
use frame_support_procedural_tools::get_doc_literals;
use quote::ToTokens;
use syn::{spanned::Spanned, Ident};
///
@@ -79,7 +80,7 @@ pub fn expand_genesis_config(def: &mut Def) -> proc_macro2::TokenStream {
let genesis_config_item =
&mut def.item.content.as_mut().expect("Checked by def parser").1[genesis_config.index];
let serde_crate = format!("{}::__private::serde", frame_support);
let serde_crate = format!("{}::__private::serde", frame_support.to_token_stream());
match genesis_config_item {
syn::Item::Enum(syn::ItemEnum { attrs, .. }) |
@@ -85,18 +85,16 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream {
// wrapped inside of braces and finally prepended with double colons, to the caller inside
// of a key named `tokens`.
//
// We need to accept a frame_support argument here, because this macro gets expanded on the
// crate that called the `construct_runtime!` macro, and said crate may have renamed
// frame-support, and so we need to pass in the frame-support path that said crate
// recognizes.
// We need to accept a path argument here, because this macro gets expanded on the
// crate that called the `construct_runtime!` macro, and the actual path is unknown.
#[macro_export]
#[doc(hidden)]
macro_rules! #default_parts_unique_id {
{
$caller:tt
frame_support = [{ $($frame_support:ident)::* }]
your_tt_return = [{ $my_tt_return:path }]
} => {
$($frame_support)*::__private::tt_return! {
$my_tt_return! {
$caller
tokens = [{
expanded::{
@@ -112,7 +110,7 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream {
pub use #default_parts_unique_id as tt_default_parts;
// This macro is similar to the `tt_default_parts!`. It expands the pallets thare are declared
// This macro is similar to the `tt_default_parts!`. It expands the pallets that are declared
// explicitly (`System: frame_system::{Pallet, Call}`) with extra parts.
//
// For example, after expansion an explicit pallet would look like:
@@ -124,9 +122,9 @@ pub fn expand_tt_default_parts(def: &mut Def) -> proc_macro2::TokenStream {
macro_rules! #extra_parts_unique_id {
{
$caller:tt
frame_support = [{ $($frame_support:ident)::* }]
your_tt_return = [{ $my_tt_return:path }]
} => {
$($frame_support)*::__private::tt_return! {
$my_tt_return! {
$caller
tokens = [{
expanded::{
@@ -92,7 +92,7 @@ impl CompositeDef {
pub fn try_from(
attr_span: proc_macro2::Span,
index: usize,
scrate: &proc_macro2::Ident,
scrate: &syn::Path,
item: &mut syn::Item,
) -> syn::Result<Self> {
let item = if let syn::Item::Enum(item) = item {
@@ -16,7 +16,7 @@
// limitations under the License.
use super::helper;
use frame_support_procedural_tools::get_doc_literals;
use frame_support_procedural_tools::{get_doc_literals, is_using_frame_crate};
use quote::ToTokens;
use syn::{spanned::Spanned, token, Token};
@@ -165,24 +165,8 @@ pub struct PalletAttr {
typ: PalletAttrType,
}
pub struct ConfigBoundParse(syn::Ident);
impl syn::parse::Parse for ConfigBoundParse {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let ident = input.parse::<syn::Ident>()?;
input.parse::<syn::Token![::]>()?;
input.parse::<keyword::Config>()?;
if input.peek(syn::token::Lt) {
input.parse::<syn::AngleBracketedGenericArguments>()?;
}
Ok(Self(ident))
}
}
/// Parse for `IsType<<Sef as $ident::Config>::RuntimeEvent>` and retrieve `$ident`
pub struct IsTypeBoundEventParse(syn::Ident);
/// Parse for `IsType<<Self as $path>::RuntimeEvent>` and retrieve `$path`
pub struct IsTypeBoundEventParse(syn::Path);
impl syn::parse::Parse for IsTypeBoundEventParse {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
@@ -191,15 +175,13 @@ impl syn::parse::Parse for IsTypeBoundEventParse {
input.parse::<syn::Token![<]>()?;
input.parse::<syn::Token![Self]>()?;
input.parse::<syn::Token![as]>()?;
let ident = input.parse::<syn::Ident>()?;
input.parse::<syn::Token![::]>()?;
input.parse::<keyword::Config>()?;
let config_path = input.parse::<syn::Path>()?;
input.parse::<syn::Token![>]>()?;
input.parse::<syn::Token![::]>()?;
input.parse::<keyword::RuntimeEvent>()?;
input.parse::<syn::Token![>]>()?;
Ok(Self(ident))
Ok(Self(config_path))
}
}
@@ -237,7 +219,7 @@ impl syn::parse::Parse for FromEventParse {
/// Check if trait_item is `type RuntimeEvent`, if so checks its bounds are those expected.
/// (Event type is reserved type)
fn check_event_type(
frame_system: &syn::Ident,
frame_system: &syn::Path,
trait_item: &syn::TraitItem,
trait_has_instance: bool,
) -> syn::Result<bool> {
@@ -249,19 +231,16 @@ fn check_event_type(
no generics nor where_clause";
return Err(syn::Error::new(trait_item.span(), msg))
}
// Check bound contains IsType and From
// Check bound contains IsType and From
let has_is_type_bound = type_.bounds.iter().any(|s| {
syn::parse2::<IsTypeBoundEventParse>(s.to_token_stream())
.map_or(false, |b| b.0 == *frame_system)
.map_or(false, |b| has_expected_system_config(b.0, frame_system))
});
if !has_is_type_bound {
let msg = format!(
"Invalid `type RuntimeEvent`, associated type `RuntimeEvent` is reserved and must \
bound: `IsType<<Self as {}::Config>::RuntimeEvent>`",
frame_system,
);
let msg = "Invalid `type RuntimeEvent`, associated type `RuntimeEvent` is reserved and must \
bound: `IsType<<Self as frame_system::Config>::RuntimeEvent>`".to_string();
return Err(syn::Error::new(type_.span(), msg))
}
@@ -295,6 +274,43 @@ fn check_event_type(
}
}
/// Check that the path to `frame_system::Config` is valid, this is that the path is just
/// `frame_system::Config` or when using the `frame` crate it is `frame::xyz::frame_system::Config`.
fn has_expected_system_config(path: syn::Path, frame_system: &syn::Path) -> bool {
// Check if `frame_system` is actually 'frame_system'.
if path.segments.iter().all(|s| s.ident != "frame_system") {
return false
}
let mut expected_system_config =
match (is_using_frame_crate(&path), is_using_frame_crate(&frame_system)) {
(true, false) =>
// We can't use the path to `frame_system` from `frame` if `frame_system` is not being
// in scope through `frame`.
return false,
(false, true) =>
// We know that the only valid frame_system path is one that is `frame_system`, as
// `frame` re-exports it as such.
syn::parse2::<syn::Path>(quote::quote!(frame_system)).expect("is a valid path; qed"),
(_, _) =>
// They are either both `frame_system` or both `frame::xyz::frame_system`.
frame_system.clone(),
};
expected_system_config
.segments
.push(syn::PathSegment::from(syn::Ident::new("Config", path.span())));
// the parse path might be something like `frame_system::Config<...>`, so we
// only compare the idents along the path.
expected_system_config
.segments
.into_iter()
.map(|ps| ps.ident)
.collect::<Vec<_>>() ==
path.segments.into_iter().map(|ps| ps.ident).collect::<Vec<_>>()
}
/// Replace ident `Self` by `T`
pub fn replace_self_by_t(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
input
@@ -311,7 +327,7 @@ pub fn replace_self_by_t(input: proc_macro2::TokenStream) -> proc_macro2::TokenS
impl ConfigDef {
pub fn try_from(
frame_system: &syn::Ident,
frame_system: &syn::Path,
attr_span: proc_macro2::Span,
index: usize,
item: &mut syn::Item,
@@ -352,8 +368,8 @@ impl ConfigDef {
};
let has_frame_system_supertrait = item.supertraits.iter().any(|s| {
syn::parse2::<ConfigBoundParse>(s.to_token_stream())
.map_or(false, |b| b.0 == *frame_system)
syn::parse2::<syn::Path>(s.to_token_stream())
.map_or(false, |b| has_expected_system_config(b, frame_system))
});
let mut has_event_type = false;
@@ -461,7 +477,8 @@ impl ConfigDef {
(try `pub trait Config: frame_system::Config {{ ...` or \
`pub trait Config<I: 'static>: frame_system::Config {{ ...`). \
To disable this check, use `#[pallet::disable_frame_system_supertrait_check]`",
frame_system, found,
frame_system.to_token_stream(),
found,
);
return Err(syn::Error::new(item.span(), msg))
}
@@ -477,3 +494,97 @@ impl ConfigDef {
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn has_expected_system_config_works() {
let frame_system = syn::parse2::<syn::Path>(quote::quote!(frame_system)).unwrap();
let path = syn::parse2::<syn::Path>(quote::quote!(frame_system::Config)).unwrap();
assert!(has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_works_with_assoc_type() {
let frame_system = syn::parse2::<syn::Path>(quote::quote!(frame_system)).unwrap();
let path =
syn::parse2::<syn::Path>(quote::quote!(frame_system::Config<RuntimeCall = Call>))
.unwrap();
assert!(has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_works_with_frame() {
let frame_system =
syn::parse2::<syn::Path>(quote::quote!(frame::deps::frame_system)).unwrap();
let path = syn::parse2::<syn::Path>(quote::quote!(frame_system::Config)).unwrap();
assert!(has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_works_with_frame_full_path() {
let frame_system =
syn::parse2::<syn::Path>(quote::quote!(frame::deps::frame_system)).unwrap();
let path =
syn::parse2::<syn::Path>(quote::quote!(frame::deps::frame_system::Config)).unwrap();
assert!(has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_works_with_other_frame_full_path() {
let frame_system =
syn::parse2::<syn::Path>(quote::quote!(frame::xyz::frame_system)).unwrap();
let path =
syn::parse2::<syn::Path>(quote::quote!(frame::xyz::frame_system::Config)).unwrap();
assert!(has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_does_not_works_with_mixed_frame_full_path() {
let frame_system =
syn::parse2::<syn::Path>(quote::quote!(frame::xyz::frame_system)).unwrap();
let path =
syn::parse2::<syn::Path>(quote::quote!(frame::deps::frame_system::Config)).unwrap();
assert!(!has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_does_not_works_with_other_mixed_frame_full_path() {
let frame_system =
syn::parse2::<syn::Path>(quote::quote!(frame::deps::frame_system)).unwrap();
let path =
syn::parse2::<syn::Path>(quote::quote!(frame::xyz::frame_system::Config)).unwrap();
assert!(!has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_does_not_work_with_frame_full_path_if_not_frame_crate() {
let frame_system = syn::parse2::<syn::Path>(quote::quote!(frame_system)).unwrap();
let path =
syn::parse2::<syn::Path>(quote::quote!(frame::deps::frame_system::Config)).unwrap();
assert!(!has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_unexpected_frame_system() {
let frame_system =
syn::parse2::<syn::Path>(quote::quote!(framez::deps::frame_system)).unwrap();
let path = syn::parse2::<syn::Path>(quote::quote!(frame_system::Config)).unwrap();
assert!(!has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_unexpected_path() {
let frame_system = syn::parse2::<syn::Path>(quote::quote!(frame_system)).unwrap();
let path = syn::parse2::<syn::Path>(quote::quote!(frame_system::ConfigSystem)).unwrap();
assert!(!has_expected_system_config(path, &frame_system));
}
#[test]
fn has_expected_system_config_not_frame_system() {
let frame_system = syn::parse2::<syn::Path>(quote::quote!(something)).unwrap();
let path = syn::parse2::<syn::Path>(quote::quote!(something::Config)).unwrap();
assert!(!has_expected_system_config(path, &frame_system));
}
}
@@ -37,7 +37,7 @@ pub mod type_value;
pub mod validate_unsigned;
use composite::{keyword::CompositeKeyword, CompositeDef};
use frame_support_procedural_tools::generate_crate_access_2018;
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use syn::spanned::Spanned;
/// Parsed definition of a pallet.
@@ -60,15 +60,15 @@ pub struct Def {
pub extra_constants: Option<extra_constants::ExtraConstantsDef>,
pub composites: Vec<composite::CompositeDef>,
pub type_values: Vec<type_value::TypeValueDef>,
pub frame_system: syn::Ident,
pub frame_support: syn::Ident,
pub frame_system: syn::Path,
pub frame_support: syn::Path,
pub dev_mode: bool,
}
impl Def {
pub fn try_from(mut item: syn::ItemMod, dev_mode: bool) -> syn::Result<Self> {
let frame_system = generate_crate_access_2018("frame-system")?;
let frame_support = generate_crate_access_2018("frame-support")?;
let frame_system = generate_access_from_frame_or_crate("frame-system")?;
let frame_support = generate_access_from_frame_or_crate("frame-support")?;
let item_span = item.span();
let items = &mut item
@@ -15,7 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use frame_support_procedural_tools::generate_crate_access_2018;
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use quote::ToTokens;
// Derive `PalletError`
@@ -25,7 +25,7 @@ pub fn derive_pallet_error(input: proc_macro::TokenStream) -> proc_macro::TokenS
Err(e) => return e.to_compile_error().into(),
};
let frame_support = match generate_crate_access_2018("frame-support") {
let frame_support = match generate_access_from_frame_or_crate("frame-support") {
Ok(c) => c,
Err(e) => return e.into_compile_error().into(),
};
@@ -111,7 +111,7 @@ pub fn derive_pallet_error(input: proc_macro::TokenStream) -> proc_macro::TokenS
fn generate_field_types(
field: &syn::Field,
scrate: &syn::Ident,
scrate: &syn::Path,
) -> syn::Result<Option<proc_macro2::TokenStream>> {
let attrs = &field.attrs;
@@ -143,7 +143,7 @@ fn generate_field_types(
fn generate_variant_field_types(
variant: &syn::Variant,
scrate: &syn::Ident,
scrate: &syn::Path,
) -> syn::Result<Option<Vec<proc_macro2::TokenStream>>> {
let attrs = &variant.attrs;
@@ -18,7 +18,7 @@
//! Implementation of the `storage_alias` attribute macro.
use crate::{counter_prefix, pallet::parse::helper};
use frame_support_procedural_tools::generate_crate_access_2018;
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use syn::{
@@ -199,7 +199,7 @@ impl StorageType {
/// Generate the actual type declaration.
fn generate_type_declaration(
&self,
crate_: &Ident,
crate_: &syn::Path,
storage_instance: &StorageInstance,
storage_name: &Ident,
storage_generics: Option<&SimpleGenerics>,
@@ -475,7 +475,7 @@ enum PrefixType {
/// Implementation of the `storage_alias` attribute macro.
pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> Result<TokenStream> {
let input = syn::parse2::<Input>(input)?;
let crate_ = generate_crate_access_2018("frame-support")?;
let crate_ = generate_access_from_frame_or_crate("frame-support")?;
let prefix_type = if attributes.is_empty() {
PrefixType::Compatibility
@@ -527,7 +527,7 @@ struct StorageInstance {
/// Generate the [`StorageInstance`] for the storage alias.
fn generate_storage_instance(
crate_: &Ident,
crate_: &syn::Path,
storage_name: &Ident,
storage_generics: Option<&SimpleGenerics>,
storage_where_clause: Option<&WhereClause>,
@@ -15,7 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use frame_support_procedural_tools::generate_crate_access_2018;
use frame_support_procedural_tools::generate_access_from_frame_or_crate;
use proc_macro::TokenStream;
use quote::quote;
use syn::{ItemFn, Result};
@@ -23,7 +23,7 @@ use syn::{ItemFn, Result};
pub fn transactional(_attr: TokenStream, input: TokenStream) -> Result<TokenStream> {
let ItemFn { attrs, vis, sig, block } = syn::parse(input)?;
let crate_ = generate_crate_access_2018("frame-support")?;
let crate_ = generate_access_from_frame_or_crate("frame-support")?;
let output = quote! {
#(#attrs)*
#vis #sig {
@@ -45,7 +45,7 @@ pub fn transactional(_attr: TokenStream, input: TokenStream) -> Result<TokenStre
pub fn require_transactional(_attr: TokenStream, input: TokenStream) -> Result<TokenStream> {
let ItemFn { attrs, vis, sig, block } = syn::parse(input)?;
let crate_ = generate_crate_access_2018("frame-support")?;
let crate_ = generate_access_from_frame_or_crate("frame-support")?;
let output = quote! {
#(#attrs)*
#vis #sig {
@@ -18,7 +18,6 @@
//! Implementation of the `create_tt_return_macro` macro
use crate::COUNTER;
use frame_support_procedural_tools::generate_crate_access_2018;
use proc_macro2::{Ident, TokenStream};
use quote::format_ident;
@@ -65,9 +64,9 @@ impl syn::parse::Parse for CreateTtReturnMacroDef {
/// macro_rules! my_tt_macro {
/// {
/// $caller:tt
/// $(frame_support = [{ $($frame_support:ident)::* }])?
/// $(your_tt_return = [{ $my_tt_return:path }])?
/// } => {
/// frame_support::__private::tt_return! {
/// $my_tt_return! {
/// $caller
/// foo = [{ bar }]
/// }
@@ -78,10 +77,6 @@ pub fn create_tt_return_macro(input: proc_macro::TokenStream) -> proc_macro::Tok
let CreateTtReturnMacroDef { name, args } =
syn::parse_macro_input!(input as CreateTtReturnMacroDef);
let frame_support = match generate_crate_access_2018("frame-support") {
Ok(i) => i,
Err(e) => return e.into_compile_error().into(),
};
let (keys, values): (Vec<_>, Vec<_>) = args.into_iter().unzip();
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
let unique_name = format_ident!("{}_{}", name, count);
@@ -92,9 +87,9 @@ pub fn create_tt_return_macro(input: proc_macro::TokenStream) -> proc_macro::Tok
macro_rules! #unique_name {
{
$caller:tt
$(frame_support = [{ $($frame_support:ident)::* }])?
$(your_tt_return = [{ $my_tt_macro:path }])?
} => {
#frame_support::__private::tt_return! {
$my_tt_return! {
$caller
#(
#keys = [{ #values }]
@@ -39,24 +39,44 @@ fn generate_hidden_includes_mod_name(unique_id: &str) -> Ident {
/// Generates the access to the `frame-support` crate.
pub fn generate_crate_access(unique_id: &str, def_crate: &str) -> TokenStream {
if std::env::var("CARGO_PKG_NAME").unwrap() == def_crate {
quote::quote!(frame_support)
let frame_support = match generate_access_from_frame_or_crate("frame-support") {
Ok(c) => c,
Err(e) => return e.into_compile_error().into(),
};
quote::quote!(#frame_support)
} else {
let mod_name = generate_hidden_includes_mod_name(unique_id);
quote::quote!( self::#mod_name::hidden_include )
}
}
/// Check if a path is using the `frame` crate or not.
///
/// This will usually check the output of [`generate_access_from_frame_or_crate`].
/// We want to know if whatever the `path` takes us to, is exported from `frame` or not. In that
/// case `path` would start with `frame`, something like `frame::x::y:z`.
pub fn is_using_frame_crate(path: &syn::Path) -> bool {
path.segments.first().map(|s| s.ident == "frame").unwrap_or(false)
}
/// Generate the crate access for the crate using 2018 syntax.
///
/// for `frame-support` output will for example be `frame_support`.
pub fn generate_crate_access_2018(def_crate: &str) -> Result<syn::Ident, Error> {
match crate_name(def_crate) {
Ok(FoundCrate::Itself) => {
let name = def_crate.to_string().replace("-", "_");
Ok(syn::Ident::new(&name, Span::call_site()))
},
Ok(FoundCrate::Name(name)) => Ok(Ident::new(&name, Span::call_site())),
Err(e) => Err(Error::new(Span::call_site(), e)),
/// If `frame` is in scope, it will use `frame::deps::<def_crate>`. Else, it will try and find
/// `<def_crate>` directly.
pub fn generate_access_from_frame_or_crate(def_crate: &str) -> Result<syn::Path, Error> {
if let Some(path) = get_frame_crate_path(def_crate) {
Ok(path)
} else {
let ident = match crate_name(def_crate) {
Ok(FoundCrate::Itself) => {
let name = def_crate.to_string().replace("-", "_");
Ok(syn::Ident::new(&name, Span::call_site()))
},
Ok(FoundCrate::Name(name)) => Ok(Ident::new(&name, Span::call_site())),
Err(e) => Err(Error::new(Span::call_site(), e)),
}?;
Ok(syn::Path::from(ident))
}
}
@@ -64,21 +84,41 @@ pub fn generate_crate_access_2018(def_crate: &str) -> Result<syn::Ident, Error>
pub fn generate_hidden_includes(unique_id: &str, def_crate: &str) -> TokenStream {
let mod_name = generate_hidden_includes_mod_name(unique_id);
match crate_name(def_crate) {
Ok(FoundCrate::Itself) => quote!(),
Ok(FoundCrate::Name(name)) => {
let name = Ident::new(&name, Span::call_site());
quote::quote!(
#[doc(hidden)]
mod #mod_name {
pub extern crate #name as hidden_include;
}
)
},
Err(e) => {
let err = Error::new(Span::call_site(), e).to_compile_error();
quote!( #err )
},
if let Some(path) = get_frame_crate_path(def_crate) {
quote::quote!(
#[doc(hidden)]
mod #mod_name {
pub use #path as hidden_include;
}
)
} else {
match crate_name(def_crate) {
Ok(FoundCrate::Itself) => quote!(),
Ok(FoundCrate::Name(name)) => {
let name = Ident::new(&name, Span::call_site());
quote::quote!(
#[doc(hidden)]
mod #mod_name {
pub extern crate #name as hidden_include;
}
)
},
Err(e) => {
let err = Error::new(Span::call_site(), e).to_compile_error();
quote!( #err )
},
}
}
}
/// Generates the path to the frame crate deps.
fn get_frame_crate_path(def_crate: &str) -> Option<syn::Path> {
// This does not work if the frame crate is renamed.
if let Ok(FoundCrate::Name(name)) = crate_name(&"frame") {
let path = format!("{}::deps::{}", name, def_crate.to_string().replace("-", "_"));
Some(syn::parse_str::<syn::Path>(&path).expect("is a valid path; qed"))
} else {
None
}
}
@@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] }
scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
renamed-frame-support = { package = "frame-support", path = "../..", default-features = false}
frame-system = { path = "../../../system", default-features = false}
renamed-frame-system = { package = "frame-system", path = "../../../system", default-features = false}
sp-core = { path = "../../../../primitives/core", default-features = false}
sp-runtime = { path = "../../../../primitives/runtime", default-features = false}
sp-version = { path = "../../../../primitives/version", default-features = false}
@@ -24,8 +24,8 @@ sp-version = { path = "../../../../primitives/version", default-features = false
default = [ "std" ]
std = [
"codec/std",
"frame-system/std",
"renamed-frame-support/std",
"renamed-frame-system/std",
"scale-info/std",
"sp-core/std",
"sp-runtime/std",
@@ -16,7 +16,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Test that `construct_runtime!` also works when `frame-support` is renamed in the `Cargo.toml`.
//! Test that `construct_runtime!` also works when `frame-support` or `frame-system` are renamed in
//! the `Cargo.toml`.
#![cfg_attr(not(feature = "std"), no_std)]
@@ -50,7 +51,7 @@ parameter_types! {
pub const Version: RuntimeVersion = VERSION;
}
impl frame_system::Config for Runtime {
impl renamed_frame_system::Config for Runtime {
type BaseCallFilter = Everything;
type BlockWeights = ();
type BlockLength = ();
@@ -82,6 +83,6 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, RuntimeCall, Sign
construct_runtime!(
pub struct Runtime {
System: frame_system,
System: renamed_frame_system,
}
);
@@ -0,0 +1,21 @@
[package]
name = "frame-support-test-stg-frame-crate"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
publish = false
homepage = "https://substrate.io"
repository.workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] }
frame = { path = "frame", default-features = false}
scale-info = { version = "2.0.0", default-features = false, features = ["derive"] }
[features]
default = [ "std" ]
std = [ "codec/std", "frame/std", "scale-info/std" ]
@@ -0,0 +1,20 @@
[package]
name = "frame"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
publish = false
homepage = "https://substrate.io"
repository.workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
frame-system = { path = "../../../../system", default-features = false}
frame-support = { path = "../../..", default-features = false}
[features]
default = [ "std" ]
std = [ "frame-support/std", "frame-system/std" ]
@@ -0,0 +1,21 @@
// 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.
pub mod deps {
pub use frame_support;
pub use frame_system;
}
@@ -0,0 +1,75 @@
// 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.
// ! A basic pallet to test it compiles along with a runtime using it when `frame_system` and
// `frame_support` are reexported by a `frame` crate.
use frame::deps::{frame_support, frame_system};
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pallet::config]
// The only valid syntax here is the following or
// ```
// pub trait Config: frame::deps::frame_system::Config {}
// ```
pub trait Config: frame_system::Config {}
#[pallet::genesis_config]
#[derive(frame_support::DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
#[serde(skip)]
_config: core::marker::PhantomData<T>,
}
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {}
}
}
#[cfg(test)]
// Dummy test to make sure a runtime would compile.
mod tests {
use super::{
frame_support::{construct_runtime, derive_impl},
frame_system, pallet,
};
type Block = frame_system::mocking::MockBlock<Runtime>;
impl crate::pallet::Config for Runtime {}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Runtime {
type Block = Block;
}
construct_runtime! {
pub struct Runtime
{
System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>},
Pallet: pallet::{Pallet, Config<T>},
}
}
}
@@ -41,5 +41,4 @@ mod pallet {
}
}
fn main() {
}
fn main() {}
@@ -0,0 +1,44 @@
// 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::{Hooks, IsType};
use frame_system::pallet_prelude::BlockNumberFor;
#[pallet::config]
pub trait Config: frame_system::Config<Hash = sp_core::H256> {
type Bar: Clone + std::fmt::Debug + Eq;
type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;
}
#[pallet::pallet]
pub struct Pallet<T>(core::marker::PhantomData<T>);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
#[pallet::call]
impl<T: Config> Pallet<T> {}
#[pallet::event]
pub enum Event<T: Config> {
B { b: T::Bar },
}
}
fn main() {}