mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 01:07:57 +00:00
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:
committed by
Gavin Wood
parent
0aab5c659e
commit
8e393aa5a8
@@ -17,18 +17,19 @@
|
||||
//! Macro for declaring a module error.
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use sp_runtime::traits::LookupError;
|
||||
pub use sp_runtime::traits::{LookupError, BadOrigin};
|
||||
#[doc(hidden)]
|
||||
pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent};
|
||||
|
||||
/// Declare an error type for a runtime module.
|
||||
///
|
||||
/// The generated error type inherently has the variants `Other` and `CannotLookup`. `Other` can
|
||||
/// hold any `&'static str` error message and is present for convenience/backward compatibility.
|
||||
/// The `CannotLookup` variant indicates that some lookup could not be done. For both variants the
|
||||
/// error type implements `From<&'static str>` and `From<LookupError>` to make them usable with the
|
||||
/// try operator.
|
||||
/// `decl_error!` supports only variants that do not hold any data. The dispatchable
|
||||
/// functions return [`DispatchResult`](sp_runtime::DispatchResult). The error type
|
||||
/// implements `From<ErrorType> for DispatchResult` to make the error type usable as error
|
||||
/// in the dispatchable functions.
|
||||
///
|
||||
/// `decl_error!` supports only variants that do not hold any data.
|
||||
/// It is required that the error type is registed in `decl_module!` to make the error
|
||||
/// exported in the metadata.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
@@ -36,7 +37,7 @@ pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent};
|
||||
/// # use frame_support::{decl_error, decl_module};
|
||||
/// decl_error! {
|
||||
/// /// Errors that can occur in my module.
|
||||
/// pub enum MyError {
|
||||
/// pub enum MyError for Module<T: Trait> {
|
||||
/// /// Hey this is an error message that indicates bla.
|
||||
/// MyCoolErrorMessage,
|
||||
/// /// You are just not cool enough for my module!
|
||||
@@ -44,27 +45,36 @@ pub use frame_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent};
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # use frame_system::{self as system, Trait, ensure_signed};
|
||||
/// # use frame_system::{self as system, Trait};
|
||||
///
|
||||
/// // You need to register the error type in `decl_module!` as well.
|
||||
/// // You need to register the error type in `decl_module!` as well to make the error
|
||||
/// // exported in the metadata.
|
||||
///
|
||||
/// decl_module! {
|
||||
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
/// type Error = MyError;
|
||||
/// type Error = MyError<T>;
|
||||
///
|
||||
/// fn do_something(origin) -> Result<(), MyError> {
|
||||
/// Err(MyError::YouAreNotCoolEnough)
|
||||
/// fn do_something(origin) -> frame_support::dispatch::DispatchResult {
|
||||
/// Err(MyError::<T>::YouAreNotCoolEnough.into())
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// For instantiable modules you also need to give the instance generic type and bound to the
|
||||
/// error declaration.
|
||||
#[macro_export]
|
||||
macro_rules! decl_error {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $error:ident {
|
||||
pub enum $error:ident
|
||||
for $module:ident<
|
||||
$generic:ident: $trait:path
|
||||
$(, $inst_generic:ident: $instance:path)?
|
||||
>
|
||||
{
|
||||
$(
|
||||
$( #[doc = $doc_attr:tt] )*
|
||||
$name:ident
|
||||
@@ -72,33 +82,42 @@ macro_rules! decl_error {
|
||||
$(,)?
|
||||
}
|
||||
) => {
|
||||
#[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)]
|
||||
$(#[$attr])*
|
||||
pub enum $error {
|
||||
Other(&'static str),
|
||||
CannotLookup,
|
||||
pub enum $error<$generic: $trait $(, $inst_generic: $instance)?> {
|
||||
#[doc(hidden)]
|
||||
__Ignore(
|
||||
$crate::sp_std::marker::PhantomData<($generic $(, $inst_generic)?)>,
|
||||
$crate::dispatch::Never,
|
||||
),
|
||||
$(
|
||||
$( #[doc = $doc_attr] )*
|
||||
$name
|
||||
),*
|
||||
}
|
||||
|
||||
impl $crate::dispatch::ModuleDispatchError for $error {
|
||||
impl<$generic: $trait $(, $inst_generic: $instance)?> $crate::sp_std::fmt::Debug
|
||||
for $error<$generic $(, $inst_generic)?>
|
||||
{
|
||||
fn fmt(&self, f: &mut $crate::sp_std::fmt::Formatter<'_>) -> $crate::sp_std::fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<$generic: $trait $(, $inst_generic: $instance)?> $error<$generic $(, $inst_generic)?> {
|
||||
fn as_u8(&self) -> u8 {
|
||||
$crate::decl_error! {
|
||||
@GENERATE_AS_U8
|
||||
self
|
||||
$error
|
||||
{}
|
||||
2,
|
||||
0,
|
||||
$( $name ),*
|
||||
}
|
||||
}
|
||||
|
||||
fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
$error::Other(err) => err,
|
||||
$error::CannotLookup => "Can not lookup",
|
||||
Self::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"),
|
||||
$(
|
||||
$error::$name => stringify!($name),
|
||||
)*
|
||||
@@ -106,33 +125,33 @@ macro_rules! decl_error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for $error {
|
||||
fn from(val: &'static str) -> $error {
|
||||
$error::Other(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$crate::error::LookupError> for $error {
|
||||
fn from(_: $crate::error::LookupError) -> $error {
|
||||
$error::CannotLookup
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$error> for &'static str {
|
||||
fn from(err: $error) -> &'static str {
|
||||
use $crate::dispatch::ModuleDispatchError;
|
||||
impl<$generic: $trait $(, $inst_generic: $instance)?> From<$error<$generic $(, $inst_generic)?>>
|
||||
for &'static str
|
||||
{
|
||||
fn from(err: $error<$generic $(, $inst_generic)?>) -> &'static str {
|
||||
err.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<$crate::dispatch::DispatchError> for $error {
|
||||
fn into(self) -> $crate::dispatch::DispatchError {
|
||||
use $crate::dispatch::ModuleDispatchError;
|
||||
$crate::dispatch::DispatchError::new(None, self.as_u8(), Some(self.as_str()))
|
||||
impl<$generic: $trait $(, $inst_generic: $instance)?> From<$error<$generic $(, $inst_generic)?>>
|
||||
for $crate::sp_runtime::DispatchError
|
||||
{
|
||||
fn from(err: $error<$generic $(, $inst_generic)?>) -> Self {
|
||||
let index = <$generic::ModuleToIndex as $crate::traits::ModuleToIndex>
|
||||
::module_to_index::<$module<$generic $(, $inst_generic)?>>()
|
||||
.expect("Every active module has an index in the runtime; qed") as u8;
|
||||
|
||||
$crate::sp_runtime::DispatchError::Module {
|
||||
index,
|
||||
error: err.as_u8(),
|
||||
message: Some(err.as_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::error::ModuleErrorMetadata for $error {
|
||||
impl<$generic: $trait $(, $inst_generic: $instance)?> $crate::error::ModuleErrorMetadata
|
||||
for $error<$generic $(, $inst_generic)?>
|
||||
{
|
||||
fn metadata() -> &'static [$crate::error::ErrorMetadata] {
|
||||
&[
|
||||
$(
|
||||
@@ -174,8 +193,7 @@ macro_rules! decl_error {
|
||||
$index:expr,
|
||||
) => {
|
||||
match $self {
|
||||
$error::Other(_) => 0,
|
||||
$error::CannotLookup => 1,
|
||||
$error::__Ignore(_, _) => unreachable!("`__Ignore` can never be constructed"),
|
||||
$( $generated )*
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user