mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 02:11:07 +00:00
Adds ability to provide defaults for types provided by construct_runtime (#14682)
* Adds ability to use defaults for verbatim types * Adds RuntimeOrigin and PalletInfo in DefaultConfig * Adds RuntimeEvent in DefaultConfig * Adds RuntimeEvent in DefaultConfig * Minor fix * Minor fix * Everything in frame_system can now have a default * Adds docs * Adds UI Test for no_bounds * Updates docs * Adds UI tests for verbatim * Minor update * Minor updates * Minor updates * Addresses review comments * Fixes test * Update frame/support/procedural/src/derive_impl.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Minor fix * Minor * Fixes build * Uses runtime_type * Fixes comment * Fixes comment * Fixes test * Uses no_aggregated_types as an option in derive_impl * Uses specific imports * Fmt * Updates doc * Update frame/support/procedural/src/derive_impl.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Update frame/support/procedural/src/derive_impl.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Addresses review comment * Addresses review comment * fmt * Renames test files * Adds docs using docify * Fixes test * Fixes UI tests --------- Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
Generated
+1
@@ -3002,6 +3002,7 @@ dependencies = [
|
||||
"sp-std",
|
||||
"sp-tracing",
|
||||
"sp-weights",
|
||||
"static_assertions",
|
||||
"tt-call",
|
||||
]
|
||||
|
||||
|
||||
@@ -220,11 +220,14 @@ pub mod pallet {
|
||||
|
||||
pub struct TestDefaultConfig;
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)]
|
||||
impl frame_system::DefaultConfig for TestDefaultConfig {}
|
||||
|
||||
#[frame_support::register_default_impl(TestDefaultConfig)]
|
||||
impl DefaultConfig for TestDefaultConfig {
|
||||
#[inject_runtime_type]
|
||||
type RuntimeEvent = ();
|
||||
|
||||
type Balance = u64;
|
||||
|
||||
type ReserveIdentifier = ();
|
||||
@@ -242,6 +245,7 @@ pub mod pallet {
|
||||
#[pallet::config(with_default)]
|
||||
pub trait Config<I: 'static = ()>: frame_system::Config {
|
||||
/// The overarching event type.
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeEvent: From<Event<Self, I>>
|
||||
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ pub mod pallet {
|
||||
/// A type providing default configurations for this pallet in testing environment.
|
||||
pub struct TestDefaultConfig;
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)]
|
||||
impl frame_system::DefaultConfig for TestDefaultConfig {}
|
||||
|
||||
#[frame_support::register_default_impl(TestDefaultConfig)]
|
||||
@@ -109,7 +109,7 @@ pub mod pallet {
|
||||
/// example, we simple derive `frame_system::config_preludes::TestDefaultConfig` again.
|
||||
pub struct OtherDefaultConfig;
|
||||
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)]
|
||||
impl frame_system::DefaultConfig for OtherDefaultConfig {}
|
||||
|
||||
#[frame_support::register_default_impl(OtherDefaultConfig)]
|
||||
@@ -147,16 +147,7 @@ pub mod tests {
|
||||
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
||||
impl frame_system::Config for Runtime {
|
||||
// these items are defined by frame-system as `no_default`, so we must specify them here.
|
||||
// Note that these are types that actually rely on the outer runtime, and can't sensibly
|
||||
// have an _independent_ default.
|
||||
type Block = Block;
|
||||
type BlockHashCount = frame_support::traits::ConstU64<10>;
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type PalletInfo = PalletInfo;
|
||||
type OnSetCode = ();
|
||||
|
||||
// all of this is coming from `frame_system::config_preludes::TestDefaultConfig`.
|
||||
|
||||
@@ -177,6 +168,17 @@ pub mod tests {
|
||||
// type BlockWeights = ();
|
||||
// type BlockLength = ();
|
||||
// type DbWeight = ();
|
||||
// type BaseCallFilter = frame_support::traits::Everything;
|
||||
// type BlockHashCount = frame_support::traits::ConstU64<10>;
|
||||
// type OnSetCode = ();
|
||||
|
||||
// These are marked as `#[inject_runtime_type]`. Hence, they are being injected as
|
||||
// types generated by `construct_runtime`.
|
||||
|
||||
// type RuntimeOrigin = RuntimeOrigin;
|
||||
// type RuntimeCall = RuntimeCall;
|
||||
// type RuntimeEvent = RuntimeEvent;
|
||||
// type PalletInfo = PalletInfo;
|
||||
|
||||
// you could still overwrite any of them if desired.
|
||||
type SS58Prefix = frame_support::traits::ConstU16<456>;
|
||||
|
||||
@@ -44,6 +44,7 @@ environmental = { version = "1.1.4", default-features = false }
|
||||
sp-genesis-builder = { version = "0.1.0", default-features=false, path = "../../primitives/genesis-builder" }
|
||||
serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
|
||||
docify = "0.2.1"
|
||||
static_assertions = "1.1.0"
|
||||
|
||||
aquamarine = { version = "0.3.2" }
|
||||
|
||||
|
||||
@@ -22,14 +22,46 @@ use macro_magic::mm_core::ForeignPath;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::{quote, ToTokens};
|
||||
use std::collections::HashSet;
|
||||
use syn::{parse2, parse_quote, spanned::Spanned, Ident, ImplItem, ItemImpl, Path, Result, Token};
|
||||
use syn::{
|
||||
parse2, parse_quote, spanned::Spanned, token, Ident, ImplItem, ItemImpl, Path, Result, Token,
|
||||
};
|
||||
|
||||
#[derive(Parse)]
|
||||
mod keyword {
|
||||
syn::custom_keyword!(inject_runtime_type);
|
||||
syn::custom_keyword!(no_aggregated_types);
|
||||
}
|
||||
|
||||
#[derive(derive_syn_parse::Parse, PartialEq, Eq)]
|
||||
pub enum PalletAttrType {
|
||||
#[peek(keyword::inject_runtime_type, name = "inject_runtime_type")]
|
||||
RuntimeType(keyword::inject_runtime_type),
|
||||
}
|
||||
|
||||
#[derive(derive_syn_parse::Parse)]
|
||||
pub struct PalletAttr {
|
||||
_pound: Token![#],
|
||||
#[bracket]
|
||||
_bracket: token::Bracket,
|
||||
#[inside(_bracket)]
|
||||
typ: PalletAttrType,
|
||||
}
|
||||
|
||||
fn get_first_item_pallet_attr<Attr>(item: &syn::ImplItemType) -> syn::Result<Option<Attr>>
|
||||
where
|
||||
Attr: syn::parse::Parse,
|
||||
{
|
||||
item.attrs.get(0).map(|a| syn::parse2(a.into_token_stream())).transpose()
|
||||
}
|
||||
|
||||
#[derive(Parse, Debug)]
|
||||
pub struct DeriveImplAttrArgs {
|
||||
pub default_impl_path: Path,
|
||||
_as: Option<Token![as]>,
|
||||
#[parse_if(_as.is_some())]
|
||||
pub disambiguation_path: Option<Path>,
|
||||
_comma: Option<Token![,]>,
|
||||
#[parse_if(_comma.is_some())]
|
||||
pub no_aggregated_types: Option<keyword::no_aggregated_types>,
|
||||
}
|
||||
|
||||
impl ForeignPath for DeriveImplAttrArgs {
|
||||
@@ -43,6 +75,8 @@ impl ToTokens for DeriveImplAttrArgs {
|
||||
tokens.extend(self.default_impl_path.to_token_stream());
|
||||
tokens.extend(self._as.to_token_stream());
|
||||
tokens.extend(self.disambiguation_path.to_token_stream());
|
||||
tokens.extend(self._comma.to_token_stream());
|
||||
tokens.extend(self.no_aggregated_types.to_token_stream());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +112,7 @@ fn combine_impls(
|
||||
foreign_impl: ItemImpl,
|
||||
default_impl_path: Path,
|
||||
disambiguation_path: Path,
|
||||
inject_runtime_types: bool,
|
||||
) -> ItemImpl {
|
||||
let (existing_local_keys, existing_unsupported_items): (HashSet<ImplItem>, HashSet<ImplItem>) =
|
||||
local_impl
|
||||
@@ -96,7 +131,20 @@ fn combine_impls(
|
||||
// do not copy colliding items that have an ident
|
||||
return None
|
||||
}
|
||||
if matches!(item, ImplItem::Type(_)) {
|
||||
if let ImplItem::Type(typ) = item.clone() {
|
||||
let mut typ = typ.clone();
|
||||
if let Ok(Some(PalletAttr { typ: PalletAttrType::RuntimeType(_), .. })) =
|
||||
get_first_item_pallet_attr::<PalletAttr>(&mut typ)
|
||||
{
|
||||
let item: ImplItem = if inject_runtime_types {
|
||||
parse_quote! {
|
||||
type #ident = #ident;
|
||||
}
|
||||
} else {
|
||||
item
|
||||
};
|
||||
return Some(item)
|
||||
}
|
||||
// modify and insert uncolliding type items
|
||||
let modified_item: ImplItem = parse_quote! {
|
||||
type #ident = <#default_impl_path as #disambiguation_path>::#ident;
|
||||
@@ -132,6 +180,7 @@ pub fn derive_impl(
|
||||
foreign_tokens: TokenStream2,
|
||||
local_tokens: TokenStream2,
|
||||
disambiguation_path: Option<Path>,
|
||||
no_aggregated_types: Option<keyword::no_aggregated_types>,
|
||||
) -> Result<TokenStream2> {
|
||||
let local_impl = parse2::<ItemImpl>(local_tokens)?;
|
||||
let foreign_impl = parse2::<ItemImpl>(foreign_tokens)?;
|
||||
@@ -151,8 +200,13 @@ pub fn derive_impl(
|
||||
};
|
||||
|
||||
// generate the combined impl
|
||||
let combined_impl =
|
||||
combine_impls(local_impl, foreign_impl, default_impl_path, disambiguation_path);
|
||||
let combined_impl = combine_impls(
|
||||
local_impl,
|
||||
foreign_impl,
|
||||
default_impl_path,
|
||||
disambiguation_path,
|
||||
no_aggregated_types.is_none(),
|
||||
);
|
||||
|
||||
Ok(quote!(#combined_impl))
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ use macro_magic::import_tokens_attr;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{quote, ToTokens};
|
||||
use std::{cell::RefCell, str::FromStr};
|
||||
use syn::{parse_macro_input, Error, ItemImpl, ItemMod};
|
||||
use syn::{parse_macro_input, Error, ItemImpl, ItemMod, TraitItemType};
|
||||
|
||||
pub(crate) const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance";
|
||||
|
||||
@@ -596,6 +596,19 @@ pub fn storage_alias(attributes: TokenStream, input: TokenStream) -> TokenStream
|
||||
///
|
||||
/// 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.
|
||||
@@ -759,6 +772,7 @@ pub fn derive_impl(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
||||
attrs.into(),
|
||||
input.into(),
|
||||
custom_attrs.disambiguation_path,
|
||||
custom_attrs.no_aggregated_types,
|
||||
)
|
||||
.unwrap_or_else(|r| r.into_compile_error())
|
||||
.into()
|
||||
@@ -774,6 +788,19 @@ pub fn no_default(_: TokenStream, _: TokenStream) -> TokenStream {
|
||||
pallet_macro_stub()
|
||||
}
|
||||
|
||||
/// The optional attribute `#[pallet::no_default_bounds]` can be attached to trait items within a
|
||||
/// `Config` trait impl that has [`#[pallet::config(with_default)]`](`macro@config`) attached.
|
||||
///
|
||||
/// Attaching this attribute to a trait item ensures that the generated trait `DefaultConfig`
|
||||
/// will not have any bounds for this trait item.
|
||||
///
|
||||
/// As an example, if you have a trait item `type AccountId: SomeTrait;` in your `Config` trait,
|
||||
/// the generated `DefaultConfig` will only have `type AccountId;` with no trait bound.
|
||||
#[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`).
|
||||
///
|
||||
@@ -843,6 +870,25 @@ pub fn register_default_impl(attrs: TokenStream, tokens: TokenStream) -> TokenSt
|
||||
}
|
||||
}
|
||||
|
||||
#[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 != "RuntimeOrigin" &&
|
||||
item.ident != "PalletInfo"
|
||||
{
|
||||
return syn::Error::new_spanned(
|
||||
item,
|
||||
"`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeOrigin` 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 {
|
||||
|
||||
@@ -52,7 +52,23 @@ Consequently, a runtime that wants to include this pallet must implement this tr
|
||||
// impossible consequently.
|
||||
match &config.default_sub_trait {
|
||||
Some(default_sub_trait) if default_sub_trait.items.len() > 0 => {
|
||||
let trait_items = &default_sub_trait.items;
|
||||
let trait_items = &default_sub_trait
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
if item.1 {
|
||||
if let syn::TraitItem::Type(item) = item.0.clone() {
|
||||
let mut item = item.clone();
|
||||
item.bounds.clear();
|
||||
syn::TraitItem::Type(item)
|
||||
} else {
|
||||
item.0.clone()
|
||||
}
|
||||
} else {
|
||||
item.0.clone()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let type_param_bounds = if default_sub_trait.has_system {
|
||||
let system = &def.frame_system;
|
||||
|
||||
@@ -34,12 +34,16 @@ mod keyword {
|
||||
syn::custom_keyword!(frame_system);
|
||||
syn::custom_keyword!(disable_frame_system_supertrait_check);
|
||||
syn::custom_keyword!(no_default);
|
||||
syn::custom_keyword!(no_default_bounds);
|
||||
syn::custom_keyword!(constant);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DefaultTrait {
|
||||
pub items: Vec<syn::TraitItem>,
|
||||
/// A bool for each sub-trait item indicates whether the item has
|
||||
/// `#[pallet::no_default_bounds]` attached to it. If true, the item will not have any bounds
|
||||
/// in the generated default sub-trait.
|
||||
pub items: Vec<(syn::TraitItem, bool)>,
|
||||
pub has_system: bool,
|
||||
}
|
||||
|
||||
@@ -142,6 +146,8 @@ impl syn::parse::Parse for DisableFrameSystemSupertraitCheck {
|
||||
pub enum PalletAttrType {
|
||||
#[peek(keyword::no_default, name = "no_default")]
|
||||
NoDefault(keyword::no_default),
|
||||
#[peek(keyword::no_default_bounds, name = "no_default_bounds")]
|
||||
NoBounds(keyword::no_default_bounds),
|
||||
#[peek(keyword::constant, name = "constant")]
|
||||
Constant(keyword::constant),
|
||||
}
|
||||
@@ -366,6 +372,7 @@ impl ConfigDef {
|
||||
|
||||
let mut already_no_default = false;
|
||||
let mut already_constant = false;
|
||||
let mut already_no_default_bounds = false;
|
||||
|
||||
while let Ok(Some(pallet_attr)) =
|
||||
helper::take_first_item_pallet_attr::<PalletAttr>(trait_item)
|
||||
@@ -403,15 +410,31 @@ impl ConfigDef {
|
||||
|
||||
already_no_default = true;
|
||||
},
|
||||
(PalletAttrType::NoBounds(_), _) => {
|
||||
if !enable_default {
|
||||
return Err(syn::Error::new(
|
||||
pallet_attr._bracket.span.join(),
|
||||
"`#[pallet:no_default_bounds]` can only be used if `#[pallet::config(with_default)]` \
|
||||
has been specified"
|
||||
))
|
||||
}
|
||||
if already_no_default_bounds {
|
||||
return Err(syn::Error::new(
|
||||
pallet_attr._bracket.span.join(),
|
||||
"Duplicate #[pallet::no_default_bounds] attribute not allowed.",
|
||||
))
|
||||
}
|
||||
already_no_default_bounds = true;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if !already_no_default && !is_event && enable_default {
|
||||
if !already_no_default && enable_default {
|
||||
default_sub_trait
|
||||
.as_mut()
|
||||
.expect("is 'Some(_)' if 'enable_default'; qed")
|
||||
.items
|
||||
.push(trait_item.clone());
|
||||
.push((trait_item.clone(), already_no_default_bounds));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -830,6 +830,21 @@ pub mod pallet_prelude {
|
||||
};
|
||||
pub use codec::{Decode, Encode, MaxEncodedLen};
|
||||
pub use frame_support::pallet_macros::*;
|
||||
/// The optional attribute `#[inject_runtime_type]` can be attached to `RuntimeCall`,
|
||||
/// `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo` in an impl statement that has
|
||||
/// `#[register_default_impl]` attached to indicate that this item is generated by
|
||||
/// `construct_runtime`.
|
||||
///
|
||||
/// Attaching this attribute to such an item ensures that the combined impl generated via
|
||||
/// [`#[derive_impl(..)]`](`macro@super::derive_impl`) will use the correct type
|
||||
/// auto-generated by `construct_runtime!`.
|
||||
#[doc = docify::embed!("src/tests/inject_runtime_type.rs", derive_impl_works_with_runtime_type_injection)]
|
||||
///
|
||||
/// However, if `no_aggregated_types` is specified while using
|
||||
/// `[`#[derive_impl(..)]`](`macro@super::derive_impl`)`, then these items are attached
|
||||
/// verbatim to the combined impl.
|
||||
#[doc = docify::embed!("src/tests/inject_runtime_type.rs", derive_impl_works_with_no_aggregated_types)]
|
||||
pub use frame_support_procedural::inject_runtime_type;
|
||||
pub use frame_support_procedural::register_default_impl;
|
||||
pub use scale_info::TypeInfo;
|
||||
pub use sp_inherents::MakeFatalError;
|
||||
@@ -2176,8 +2191,8 @@ pub mod pallet_macros {
|
||||
call_index, compact, composite_enum, config, constant,
|
||||
disable_frame_system_supertrait_check, error, event, extra_constants, generate_deposit,
|
||||
generate_store, genesis_build, genesis_config, getter, hooks, import_section, inherent,
|
||||
no_default, origin, pallet_section, storage, storage_prefix, storage_version, type_value,
|
||||
unbounded, validate_unsigned, weight, whitelist_storage,
|
||||
no_default, no_default_bounds, origin, pallet_section, storage, storage_prefix,
|
||||
storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{Config, Runtime};
|
||||
use crate::{derive_impl, pallet_prelude::inject_runtime_type};
|
||||
use static_assertions::assert_type_eq_all;
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn derive_impl_works_with_runtime_type_injection() {
|
||||
assert_type_eq_all!(<Runtime as Config>::RuntimeOrigin, super::RuntimeOrigin);
|
||||
assert_type_eq_all!(<Runtime as Config>::RuntimeCall, super::RuntimeCall);
|
||||
assert_type_eq_all!(<Runtime as Config>::PalletInfo, super::PalletInfo);
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
#[test]
|
||||
fn derive_impl_works_with_no_aggregated_types() {
|
||||
struct DummyRuntime;
|
||||
|
||||
#[derive_impl(
|
||||
super::frame_system::config_preludes::TestDefaultConfig as super::frame_system::DefaultConfig,
|
||||
no_aggregated_types
|
||||
)]
|
||||
impl Config for DummyRuntime {
|
||||
type Block = super::Block;
|
||||
type AccountId = super::AccountId;
|
||||
type PalletInfo = super::PalletInfo;
|
||||
}
|
||||
|
||||
assert_type_eq_all!(<DummyRuntime as Config>::RuntimeOrigin, ());
|
||||
assert_type_eq_all!(<DummyRuntime as Config>::RuntimeCall, ());
|
||||
}
|
||||
@@ -25,6 +25,7 @@ use sp_runtime::{generic, traits::BlakeTwo256, BuildStorage};
|
||||
|
||||
pub use self::frame_system::{pallet_prelude::*, Config, Pallet};
|
||||
|
||||
mod inject_runtime_type;
|
||||
mod storage_alias;
|
||||
|
||||
#[pallet]
|
||||
@@ -34,17 +35,40 @@ pub mod frame_system {
|
||||
pub use crate::dispatch::RawOrigin;
|
||||
use crate::pallet_prelude::*;
|
||||
|
||||
pub mod config_preludes {
|
||||
use super::{inject_runtime_type, DefaultConfig};
|
||||
pub struct TestDefaultConfig;
|
||||
|
||||
#[crate::register_default_impl(TestDefaultConfig)]
|
||||
impl DefaultConfig for TestDefaultConfig {
|
||||
type AccountId = u64;
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
#[inject_runtime_type]
|
||||
type RuntimeOrigin = ();
|
||||
#[inject_runtime_type]
|
||||
type RuntimeCall = ();
|
||||
#[inject_runtime_type]
|
||||
type PalletInfo = ();
|
||||
type DbWeight = ();
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
pub struct Pallet<T>(_);
|
||||
|
||||
#[pallet::config]
|
||||
#[pallet::config(with_default)]
|
||||
#[pallet::disable_frame_system_supertrait_check]
|
||||
pub trait Config: 'static {
|
||||
#[pallet::no_default]
|
||||
type Block: Parameter + sp_runtime::traits::Block;
|
||||
type AccountId;
|
||||
#[pallet::no_default_bounds]
|
||||
type BaseCallFilter: crate::traits::Contains<Self::RuntimeCall>;
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeOrigin;
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeCall;
|
||||
#[pallet::no_default_bounds]
|
||||
type PalletInfo: crate::traits::PalletInfo;
|
||||
type DbWeight: Get<crate::weights::RuntimeDbWeight>;
|
||||
}
|
||||
@@ -168,14 +192,10 @@ crate::construct_runtime!(
|
||||
}
|
||||
);
|
||||
|
||||
#[crate::derive_impl(self::frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
|
||||
impl Config for Runtime {
|
||||
type Block = Block;
|
||||
type AccountId = AccountId;
|
||||
type BaseCallFilter = crate::traits::Everything;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type PalletInfo = PalletInfo;
|
||||
type DbWeight = ();
|
||||
}
|
||||
|
||||
fn new_test_ext() -> TestExternalities {
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
use frame_support::{*, pallet_prelude::inject_runtime_type};
|
||||
use static_assertions::assert_type_eq_all;
|
||||
|
||||
pub trait Config {
|
||||
type RuntimeCall;
|
||||
}
|
||||
|
||||
struct Pallet;
|
||||
|
||||
#[register_default_impl(Pallet)]
|
||||
impl Config for Pallet {
|
||||
#[inject_runtime_type]
|
||||
type RuntimeCall = ();
|
||||
}
|
||||
|
||||
struct SomePallet;
|
||||
|
||||
#[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall;
|
||||
impl Config for SomePallet {}
|
||||
|
||||
assert_type_eq_all!(<SomePallet as Config>::RuntimeCall, u32);
|
||||
|
||||
fn main() {}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
error[E0412]: cannot find type `RuntimeCall` in this scope
|
||||
--> tests/derive_impl_ui/inject_runtime_type_fails_when_type_not_in_scope.rs:13:10
|
||||
|
|
||||
13 | type RuntimeCall = ();
|
||||
| ^^^^^^^^^^^ help: you might have meant to use the associated type: `Self::RuntimeCall`
|
||||
...
|
||||
18 | #[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall;
|
||||
| ---------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `__export_tokens_tt_pallet` which comes from the expansion of the macro `frame_support::macro_magic::forward_tokens` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
@@ -0,0 +1,25 @@
|
||||
use frame_support::{*, pallet_prelude::inject_runtime_type};
|
||||
use static_assertions::assert_type_eq_all;
|
||||
|
||||
pub trait Config {
|
||||
type RuntimeInfo;
|
||||
}
|
||||
|
||||
type RuntimeInfo = u32;
|
||||
|
||||
struct Pallet;
|
||||
|
||||
#[register_default_impl(Pallet)]
|
||||
impl Config for Pallet {
|
||||
#[inject_runtime_type]
|
||||
type RuntimeInfo = ();
|
||||
}
|
||||
|
||||
struct SomePallet;
|
||||
|
||||
#[derive_impl(Pallet)] // Injects type RuntimeInfo = RuntimeInfo;
|
||||
impl Config for SomePallet {}
|
||||
|
||||
assert_type_eq_all!(<SomePallet as Config>::RuntimeInfo, u32);
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,14 @@
|
||||
error: `#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeOrigin` or `PalletInfo`
|
||||
--> tests/derive_impl_ui/inject_runtime_type_invalid.rs:15:5
|
||||
|
|
||||
15 | type RuntimeInfo = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `RuntimeInfo`
|
||||
--> tests/derive_impl_ui/inject_runtime_type_invalid.rs:13:1
|
||||
|
|
||||
5 | type RuntimeInfo;
|
||||
| ---------------- `RuntimeInfo` from trait
|
||||
...
|
||||
13 | impl Config for Pallet {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ missing `RuntimeInfo` in implementation
|
||||
@@ -0,0 +1,25 @@
|
||||
use frame_support::{*, pallet_prelude::inject_runtime_type};
|
||||
use static_assertions::assert_type_eq_all;
|
||||
|
||||
pub trait Config {
|
||||
type RuntimeCall;
|
||||
}
|
||||
|
||||
type RuntimeCall = u32;
|
||||
|
||||
struct Pallet;
|
||||
|
||||
#[register_default_impl(Pallet)]
|
||||
impl Config for Pallet {
|
||||
#[inject_runtime_type]
|
||||
type RuntimeCall = ();
|
||||
}
|
||||
|
||||
struct SomePallet;
|
||||
|
||||
#[derive_impl(Pallet)] // Injects type RuntimeCall = RuntimeCall;
|
||||
impl Config for SomePallet {}
|
||||
|
||||
assert_type_eq_all!(<SomePallet as Config>::RuntimeCall, u32);
|
||||
|
||||
fn main() {}
|
||||
+1
-1
@@ -5,7 +5,7 @@ mod pallet {
|
||||
#[pallet::config(with_default)]
|
||||
pub trait Config: frame_system::Config {
|
||||
#[pallet::constant]
|
||||
type MyGetParam2: Get<Self::RuntimeCall>;
|
||||
type MyGetParam2: Get<Self::Block>;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
error[E0220]: associated type `RuntimeCall` not found for `Self`
|
||||
error[E0220]: associated type `Block` not found for `Self`
|
||||
--> tests/pallet_ui/default_config_with_no_default_in_system.rs:8:31
|
||||
|
|
||||
8 | type MyGetParam2: Get<Self::RuntimeCall>;
|
||||
| ^^^^^^^^^^^ associated type `RuntimeCall` not found
|
||||
8 | type MyGetParam2: Get<Self::Block>;
|
||||
| ^^^^^ there is a similarly named associated type `Block` in the trait `frame_system::Config`
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#[frame_support::pallet]
|
||||
mod pallet {
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
#[pallet::constant]
|
||||
#[pallet::no_default_bounds]
|
||||
type MyGetParam2: Get<u32>;
|
||||
}
|
||||
|
||||
#[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> {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
error: `#[pallet:no_default_bounds]` can only be used if `#[pallet::config(with_default)]` has been specified
|
||||
--> tests/pallet_ui/no_default_bounds_but_missing_with_default.rs:9:4
|
||||
|
|
||||
9 | #[pallet::no_default_bounds]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -205,7 +205,7 @@ pub mod pallet {
|
||||
|
||||
/// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`].
|
||||
pub mod config_preludes {
|
||||
use super::DefaultConfig;
|
||||
use super::{inject_runtime_type, DefaultConfig};
|
||||
|
||||
/// Provides a viable default config that can be used with
|
||||
/// [`derive_impl`](`frame_support::derive_impl`) to derive a testing pallet config
|
||||
@@ -232,6 +232,17 @@ pub mod pallet {
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = ();
|
||||
#[inject_runtime_type]
|
||||
type RuntimeEvent = ();
|
||||
#[inject_runtime_type]
|
||||
type RuntimeOrigin = ();
|
||||
#[inject_runtime_type]
|
||||
type RuntimeCall = ();
|
||||
#[inject_runtime_type]
|
||||
type PalletInfo = ();
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type BlockHashCount = frame_support::traits::ConstU64<10>;
|
||||
type OnSetCode = ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +251,7 @@ pub mod pallet {
|
||||
#[pallet::disable_frame_system_supertrait_check]
|
||||
pub trait Config: 'static + Eq + Clone {
|
||||
/// The aggregated event type of the runtime.
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeEvent: Parameter
|
||||
+ Member
|
||||
+ From<Event<Self>>
|
||||
@@ -256,7 +268,7 @@ pub mod pallet {
|
||||
/// [`frame_support::traits::InsideBoth`], [`frame_support::traits::TheseExcept`] or
|
||||
/// [`frame_support::traits::EverythingBut`] et al. The default would be
|
||||
/// [`frame_support::traits::Everything`].
|
||||
#[pallet::no_default]
|
||||
#[pallet::no_default_bounds]
|
||||
type BaseCallFilter: Contains<Self::RuntimeCall>;
|
||||
|
||||
/// Block & extrinsics weights: base values and limits.
|
||||
@@ -268,14 +280,14 @@ pub mod pallet {
|
||||
type BlockLength: Get<limits::BlockLength>;
|
||||
|
||||
/// The `RuntimeOrigin` type used by dispatchable calls.
|
||||
#[pallet::no_default]
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeOrigin: Into<Result<RawOrigin<Self::AccountId>, Self::RuntimeOrigin>>
|
||||
+ From<RawOrigin<Self::AccountId>>
|
||||
+ Clone
|
||||
+ OriginTrait<Call = Self::RuntimeCall, AccountId = Self::AccountId>;
|
||||
|
||||
/// The aggregated `RuntimeCall` type.
|
||||
#[pallet::no_default]
|
||||
#[pallet::no_default_bounds]
|
||||
type RuntimeCall: Parameter
|
||||
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin>
|
||||
+ Debug
|
||||
@@ -335,7 +347,7 @@ pub mod pallet {
|
||||
|
||||
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
|
||||
#[pallet::constant]
|
||||
#[pallet::no_default]
|
||||
#[pallet::no_default_bounds]
|
||||
type BlockHashCount: Get<BlockNumberFor<Self>>;
|
||||
|
||||
/// The weight of runtime database operations the runtime can invoke.
|
||||
@@ -350,7 +362,9 @@ pub mod pallet {
|
||||
///
|
||||
/// Expects the `PalletInfo` type that is being generated by `construct_runtime!` in the
|
||||
/// runtime.
|
||||
#[pallet::no_default]
|
||||
///
|
||||
/// For tests it is okay to use `()` as type, however it will provide "useless" data.
|
||||
#[pallet::no_default_bounds]
|
||||
type PalletInfo: PalletInfo;
|
||||
|
||||
/// Data to be associated with an account (other than nonce/transaction counter, which this
|
||||
@@ -382,7 +396,7 @@ pub mod pallet {
|
||||
/// [`Pallet::update_code_in_storage`]).
|
||||
/// It's unlikely that this needs to be customized, unless you are writing a parachain using
|
||||
/// `Cumulus`, where the actual code change is deferred.
|
||||
#[pallet::no_default]
|
||||
#[pallet::no_default_bounds]
|
||||
type OnSetCode: SetCode<Self>;
|
||||
|
||||
/// The maximum number of consumers allowed on a single account.
|
||||
|
||||
Reference in New Issue
Block a user