Skip to content

Commit

Permalink
update genesis_config related docs and tests and error messages (pa…
Browse files Browse the repository at this point in the history
…ritytech#1642)

Follow-up to paritytech/substrate#14306.

I hope this also showcases the important message of: **It is really not
that hard to make the examples codes in rust-docs compile, and therefore
remain correct. Please embrace this :)**

It moves the documentation of proc macros to their re-export, such that
can link other items in frame-support. This is a patter that we should
embrace for all of macro docs, and apply in PRs like
paritytech/substrate#13987 as well.

---------

Co-authored-by: Gonçalo Pestana <[email protected]>
Co-authored-by: joe petrowski <[email protected]>
Co-authored-by: command-bot <>
  • Loading branch information
3 people authored Sep 22, 2023
1 parent d349b45 commit 068023a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 52 deletions.
46 changes: 0 additions & 46 deletions substrate/frame/support/procedural/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1417,57 +1417,11 @@ pub fn type_value(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
}

/// The `#[pallet::genesis_config]` attribute allows you to define the genesis configuration
/// for the pallet.
///
/// Item is defined as either an enum or a struct. It needs to be public and implement the
/// trait `GenesisBuild` with [`#[pallet::genesis_build]`](`macro@genesis_build`). The type
/// generics are constrained to be either none, or `T` or `T: Config`.
///
/// E.g:
///
/// ```ignore
/// #[pallet::genesis_config]
/// pub struct GenesisConfig<T: Config> {
/// _myfield: BalanceOf<T>,
/// }
/// ```
#[proc_macro_attribute]
pub fn genesis_config(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
}

/// The `#[pallet::genesis_build]` attribute allows you to define how `genesis_configuration`
/// is built. This takes as input the `GenesisConfig` type (as `self`) and constructs the pallet's
/// initial state.
///
/// The impl must be defined as:
///
/// ```ignore
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig<$maybe_generics> {
/// fn build(&self) { $expr }
/// }
/// ```
///
/// I.e. a trait implementation with generic `T: Config`, of trait `GenesisBuild<T>` on
/// type `GenesisConfig` with generics none or `T`.
///
/// E.g.:
///
/// ```ignore
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig {
/// fn build(&self) {}
/// }
/// ```
///
/// ## Macro expansion
///
/// The macro will add the following attribute:
/// * `#[cfg(feature = "std")]`
///
/// The macro will implement `sp_runtime::BuildStorage`.
#[proc_macro_attribute]
pub fn genesis_build(_: TokenStream, _: TokenStream) -> TokenStream {
pallet_macro_stub()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub fn expand_genesis_build(def: &mut Def) -> proc_macro2::TokenStream {
#[cfg(feature = "std")]
impl<#type_impl_gen> #frame_support::sp_runtime::BuildStorage for #gen_cfg_ident<#gen_cfg_use_gen> #where_clause
{
fn assimilate_storage(&self, storage: &mut sp_runtime::Storage) -> std::result::Result<(), std::string::String> {
fn assimilate_storage(&self, storage: &mut #frame_support::sp_runtime::Storage) -> std::result::Result<(), std::string::String> {
#frame_support::__private::BasicExternalities::execute_with_storage(storage, || {
self.build();
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ pub fn check_type_def_gen(
/// return the instance if found for `GenesisBuild`
/// return None for BuildGenesisConfig
pub fn check_genesis_builder_usage(type_: &syn::Path) -> syn::Result<Option<InstanceUsage>> {
let expected = "expected `GenesisBuild<T>` or `GenesisBuild<T, I>`";
let expected = "expected `BuildGenesisConfig` (or the deprecated `GenesisBuild<T>` or `GenesisBuild<T, I>`)";
pub struct Checker(Option<InstanceUsage>);
impl syn::parse::Parse for Checker {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Expand Down
76 changes: 73 additions & 3 deletions substrate/frame/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2188,10 +2188,80 @@ pub mod pallet_macros {
pub use frame_support_procedural::{
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, no_default_bounds, origin, pallet_section, storage, storage_prefix,
storage_version, type_value, unbounded, validate_unsigned, weight, whitelist_storage,
generate_store, getter, hooks, import_section, inherent, no_default, no_default_bounds,
origin, pallet_section, storage, storage_prefix, storage_version, type_value, unbounded,
validate_unsigned, weight, whitelist_storage,
};

/// Allows you to define the genesis configuration for the pallet.
///
/// Item is defined as either an enum or a struct. It needs to be public and implement the
/// trait [`frame_support::traits::BuildGenesisConfig`].
///
/// See [`genesis_build`] for an example.
pub use frame_support_procedural::genesis_config;

/// Allows you to define how the state of your pallet at genesis is built. This
/// takes as input the `GenesisConfig` type (as `self`) and constructs the pallet's initial
/// state.
///
/// The fields of the `GenesisConfig` can in turn be populated by the chain-spec.
///
/// ## Example:
///
/// ```
/// #[frame_support::pallet]
/// pub mod pallet {
/// # #[pallet::config]
/// # pub trait Config: frame_system::Config {}
/// # #[pallet::pallet]
/// # pub struct Pallet<T>(_);
/// # use frame_support::traits::BuildGenesisConfig;
/// #[pallet::genesis_config]
/// #[derive(frame_support::DefaultNoBound)]
/// pub struct GenesisConfig<T: Config> {
/// foo: Vec<T::AccountId>
/// }
///
/// #[pallet::genesis_build]
/// impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
/// fn build(&self) {
/// // use &self to access fields.
/// let foo = &self.foo;
/// todo!()
/// }
/// }
/// }
/// ```
///
/// ## Former Usage
///
/// Prior to <https://github.com/paritytech/substrate/pull/14306>, the following syntax was used.
/// This is deprecated and will soon be removed.
///
/// ```
/// #[frame_support::pallet]
/// pub mod pallet {
/// # #[pallet::config]
/// # pub trait Config: frame_system::Config {}
/// # #[pallet::pallet]
/// # pub struct Pallet<T>(_);
/// # use frame_support::traits::GenesisBuild;
/// #[pallet::genesis_config]
/// #[derive(frame_support::DefaultNoBound)]
/// pub struct GenesisConfig<T: Config> {
/// foo: Vec<T::AccountId>
/// }
///
/// #[pallet::genesis_build]
/// impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
/// fn build(&self) {
/// todo!()
/// }
/// }
/// }
/// ```
pub use frame_support_procedural::genesis_build;
}

#[deprecated(note = "Will be removed after July 2023; Use `sp_runtime::traits` directly instead.")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Invalid genesis builder: expected `GenesisBuild<T>` or `GenesisBuild<T, I>`
error: Invalid genesis builder: expected `BuildGenesisConfig` (or the deprecated `GenesisBuild<T>` or `GenesisBuild<T, I>`)
--> tests/pallet_ui/genesis_invalid_generic.rs:36:7
|
36 | impl GenesisBuild for GenesisConfig {}
Expand Down

0 comments on commit 068023a

Please sign in to comment.