Make decl_error! errors usable (#4449)

* Make `decl_error!` errors usable

This pr implements support for returning errors of different pallets in
a pallet. These errors need to be declared with `decl_error!`.

The pr changes the following:

- Each dispatchable function now returns a `DispatchResult` which is an
alias for `Result<(), DispatchError>`.
- `DispatchError` is an enum that has 4 variants:
  - `Other`: For storing string error messages
  - `CannotLookup`: Variant that is returned when something returns a
  `sp_runtime::LookupError`
  - `BadOrigin`: Variant that is returned for any kind of bad origin
  - `Module`: The error of a specific module. Contains the `index`,
  `error` and the `message`. The index is the index of the module in
  `construct_runtime!`. `error` is the index of the error in the error
  enum declared by `decl_error!`. `message` is the message to the error
  variant (this will not be encoded).
- `construct_runtime!` now creates a new struct `ModuleToIndex`. This
struct implements the trait `ModuleToIndex`.
- `frame_system::Trait` has a new associated type: `ModuleToIndex` that
expects the `ModuleToIndex` generated by `construct_runtime!`.
- All error strings returned in any module are being converted now to `DispatchError`.
- `BadOrigin` is the default error returned by any type that implements `EnsureOrigin`.

* Fix frame system benchmarks
This commit is contained in:
Bastian Köcher
2019-12-19 14:01:52 +01:00
committed by Gavin Wood
parent 0aab5c659e
commit 8e393aa5a8
69 changed files with 868 additions and 611 deletions
@@ -24,6 +24,9 @@ use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use syn::{Ident, Result};
/// The fixed name of the system module.
const SYSTEM_MODULE_NAME: &str = "System";
pub fn construct_runtime(input: TokenStream) -> TokenStream {
let definition = syn::parse_macro_input!(input as RuntimeDefinition);
construct_runtime_parsed(definition)
@@ -63,7 +66,7 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
let scrate = generate_crate_access(&hidden_crate_name, "frame-support");
let scrate_decl = generate_hidden_includes(&hidden_crate_name, "frame-support");
let all_but_system_modules = modules.iter().filter(|module| module.name != "System");
let all_but_system_modules = modules.iter().filter(|module| module.name != SYSTEM_MODULE_NAME);
let outer_event = decl_outer_event_or_origin(
&name,
@@ -79,7 +82,8 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
&scrate,
DeclOuterKind::Origin,
)?;
let all_modules = decl_all_modules(&name, &system_module, all_but_system_modules);
let all_modules = decl_all_modules(&name, modules.iter());
let module_to_index = decl_module_to_index(modules.iter(), modules.len(), &scrate);
let dispatch = decl_outer_dispatch(&name, modules.iter(), &scrate);
let metadata = decl_runtime_metadata(&name, modules.iter(), &scrate);
@@ -106,6 +110,8 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
#all_modules
#module_to_index
#dispatch
#metadata
@@ -308,7 +314,6 @@ fn decl_outer_event_or_origin<'a>(
fn decl_all_modules<'a>(
runtime: &'a Ident,
system_name: &'a Ident,
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
) -> TokenStream2 {
let mut types = TokenStream2::new();
@@ -330,22 +335,49 @@ fn decl_all_modules<'a>(
names.push(&module_declaration.name);
}
// Make nested tuple structure like (((Babe, Consensus), Grandpa), ...)
let all_modules = names.iter().fold(
TokenStream2::default(),
|combined, name| quote!((#name, #combined)),
);
// But ignore the system module.
let all_modules = names.iter()
.filter(|n| **n != SYSTEM_MODULE_NAME)
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
quote!(
pub type System = #system_name::Module<#runtime>;
#types
type AllModules = ( #all_modules );
)
}
fn decl_module_to_index<'a>(
module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
num_modules: usize,
scrate: &TokenStream2,
) -> TokenStream2 {
let names = module_declarations.map(|d| &d.name);
let indices = 0..num_modules;
quote!(
/// Provides an implementation of `ModuleToIndex` to map a module
/// to its index in the runtime.
pub struct ModuleToIndex;
impl #scrate::traits::ModuleToIndex for ModuleToIndex {
fn module_to_index<M: 'static>() -> Option<usize> {
let type_id = #scrate::sp_std::any::TypeId::of::<M>();
#(
if type_id == #scrate::sp_std::any::TypeId::of::<#names>() {
return Some(#indices)
}
)*
None
}
}
)
}
fn find_system_module<'a>(
mut module_declarations: impl Iterator<Item = &'a ModuleDeclaration>,
) -> Option<&'a Ident> {
module_declarations
.find(|decl| decl.name == "System")
.find(|decl| decl.name == SYSTEM_MODULE_NAME)
.map(|decl| &decl.module)
}