Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Issue compiler error when construct_runtime attempts to import a non-existing pallet part #8945

Closed
KiChjang opened this issue May 29, 2021 · 3 comments · Fixed by #8949
Closed
Assignees

Comments

@KiChjang
Copy link
Contributor

When I have the following pallet defined:

#[frame_support::pallet]
pub mod pallet {
    #[pallet::pallet]
    pub struct Pallet<T>(_);

    #[pallet::config]
    pub trait Config: frame_system::Config {}
}

and have this corresponding runtime:

construct_runtime!(
    //...
    Pallet: pallet::{Pallet, Call},
)

Compilation should fail, since pallet does not contain a #[pallet::call] defining the calls for the pallet.

@KiChjang KiChjang self-assigned this May 29, 2021
@KiChjang
Copy link
Contributor Author

Initial idea was to continue to generate the Call enum, but tag it with #[deprecated = "#[pallet::call] not defined, did you forget to include it?"], so that when construct_runtime references the Call enum during macro expansion, user would get the deprecation notice, informing them of a missing Call part.

However, deprecation notices are issued at the warning level, so it easily gets drowned out by other warnings and error messages, so the better way is to generate a compile_error! when construct_runtime attempts to reference something that is not there.

@KiChjang
Copy link
Contributor Author

Next iteration of the idea is to generate a declarative macro __is_call_part_defined during macro expansion of #[frame_support::pallet], and if #[pallet::call] is defined, the body of this declarative macro will be empty, otherwise it will contain a compile_error!. construct_runtime! will then make use of __is_call_part_defined during its expansion to check if the pallet has #[pallet::call] defined, which will generate the compiler error as expected.

However, there seems to be issues generating a declarative macro during a proc macro expansion. I've opened dtolnay/quote#185 to see whether Rust currently supports what I am trying to do. If not, then the alternative solution would be to create a static HashMap that houses all the declared parts for a pallet. construct_runtime! will then query this HashMap to check and see if a given pallet part exists, but the tricky part about this solution is figuring out what the keys should be for the HashMap.

@gui1117
Copy link
Contributor

gui1117 commented Jun 2, 2021

some thoughts:

  • this could also make use of the technique used in Allow pallet to declare its default parts and make construct_runtime automatically use them by default #8084 in order to get what are the available part in a pallet.
  • we should be able to use your technique to get if "std" is enabled or not for the pallet. And if "std" is not enabled while compiling in "std", then we should be a good error message. Because when the runtime needs to build the genesis config of a pallet, and the pallet is compiled without "std" then the error message is that GenesisConfig type doesn't exist and people get confused.

@ghost ghost closed this as completed in #8949 Jun 16, 2021
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants