DispatchError::Module is now a tuple variant in latest Substrate (#439)

* ModuleError is now a tuple variant

* more robust pointer to DispatchError

* backward compat

* clippy

* cargo fmt

* abort_call_site and simplify path comparison

* clippy
This commit is contained in:
James Wilson
2022-02-15 16:15:13 +00:00
committed by GitHub
parent 117e2edad4
commit cb9177aaa9
2 changed files with 68 additions and 11 deletions
+67 -10
View File
@@ -19,7 +19,9 @@ use proc_macro2::{
Span as Span2,
TokenStream as TokenStream2,
};
use proc_macro_error::abort_call_site;
use quote::quote;
use scale_info::TypeDef;
/// Tokens which allow us to provide static error information in the generated output.
pub struct ErrorDetails {
@@ -71,17 +73,48 @@ pub fn generate_error_details(metadata: &RuntimeMetadataV14) -> ErrorDetails {
}
});
ErrorDetails {
type_def: quote! {
pub struct ErrorDetails {
pub pallet: &'static str,
pub error: &'static str,
pub docs: &'static str,
}
},
dispatch_error_impl_fn: quote! {
let dispatch_error_def = metadata
.types
.types()
.iter()
.find(|&ty| ty.ty().path().segments() == ["sp_runtime", "DispatchError"])
.unwrap_or_else(|| {
abort_call_site!("sp_runtime::DispatchError type expected in metadata")
})
.ty()
.type_def();
// Slightly older versions of substrate have a `DispatchError::Module { index, error }`
// variant. Newer versions have something like a `DispatchError::Module (Details)` variant.
// We check to see which type of variant we're dealing with based on the metadata, and
// generate the correct code to handle either older or newer substrate versions.
let module_variant_is_struct = if let TypeDef::Variant(details) = dispatch_error_def {
let module_variant = details
.variants()
.iter()
.find(|variant| variant.name() == "Module")
.unwrap_or_else(|| {
abort_call_site!("DispatchError::Module variant expected in metadata")
});
let are_fields_named = module_variant
.fields()
.get(0)
.unwrap_or_else(|| {
abort_call_site!(
"DispatchError::Module expected to contain 1 or more fields"
)
})
.name()
.is_some();
are_fields_named
} else {
false
};
let dispatch_error_impl_fn = if module_variant_is_struct {
quote! {
pub fn details(&self) -> Option<ErrorDetails> {
if let Self::Module { index, error } = self {
if let Self::Module { error, index } = self {
match (index, error) {
#( #match_body_items ),*,
_ => None
@@ -90,7 +123,31 @@ pub fn generate_error_details(metadata: &RuntimeMetadataV14) -> ErrorDetails {
None
}
}
}
} else {
quote! {
pub fn details(&self) -> Option<ErrorDetails> {
if let Self::Module (module_error) = self {
match (module_error.index, module_error.error) {
#( #match_body_items ),*,
_ => None
}
} else {
None
}
}
}
};
ErrorDetails {
type_def: quote! {
pub struct ErrorDetails {
pub pallet: &'static str,
pub error: &'static str,
pub docs: &'static str,
}
},
dispatch_error_impl_fn,
}
}
+1 -1
View File
@@ -284,7 +284,7 @@ impl RuntimeGenerator {
#types_mod
/// The default error type returned when there is a runtime issue.
pub type DispatchError = self::runtime_types::sp_runtime::DispatchError;
pub type DispatchError = #types_mod_ident::sp_runtime::DispatchError;
// Statically generate error information so that we don't need runtime metadata for it.
#error_type