diff --git a/core/externalities/src/extensions.rs b/core/externalities/src/extensions.rs index c7d7bc48538ac..a1a83cb197d4f 100644 --- a/core/externalities/src/extensions.rs +++ b/core/externalities/src/extensions.rs @@ -27,7 +27,12 @@ use std::{collections::HashMap, any::{Any, TypeId}, ops::DerefMut}; /// /// As extensions are stored as `Box`, this trait should give more confidence that the correct /// type is registered and requested. -pub trait Extension: Sized {} +pub trait Extension: Send + Any { + /// Return the extension as `&mut dyn Any`. + /// + /// This is a trick to make the trait type castable into an `Any`. + fn as_mut_any(&mut self) -> &mut dyn Any; +} /// Macro for declaring an extension that usable with [`Extensions`]. /// @@ -51,7 +56,11 @@ macro_rules! decl_extension { $( #[ $attr ] )* $vis struct $ext_name (pub $inner); - impl $crate::Extension for $ext_name {} + impl $crate::Extension for $ext_name { + fn as_mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + } impl std::ops::Deref for $ext_name { type Target = $inner; @@ -83,7 +92,7 @@ pub trait ExtensionStore { /// Stores extensions that should be made available through the externalities. #[derive(Default)] pub struct Extensions { - extensions: HashMap>, + extensions: HashMap>, } impl Extensions { @@ -93,13 +102,13 @@ impl Extensions { } /// Register the given extension. - pub fn register(&mut self, ext: E) { + pub fn register(&mut self, ext: E) { self.extensions.insert(ext.type_id(), Box::new(ext)); } /// Return a mutable reference to the requested extension. pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> { - self.extensions.get_mut(&ext_type_id).map(DerefMut::deref_mut) + self.extensions.get_mut(&ext_type_id).map(DerefMut::deref_mut).map(Extension::as_mut_any) } } @@ -107,11 +116,12 @@ impl Extensions { mod tests { use super::*; - struct DummyExt(u32); - impl Extension for DummyExt {} - - struct DummyExt2(u32); - impl Extension for DummyExt2 {} + decl_extension! { + struct DummyExt(u32); + } + decl_extension! { + struct DummyExt2(u32); + } #[test] fn register_and_retrieve_extension() { diff --git a/core/primitives/src/offchain.rs b/core/primitives/src/offchain.rs index 27bd29a00df8d..c69c074b747b1 100644 --- a/core/primitives/src/offchain.rs +++ b/core/primitives/src/offchain.rs @@ -289,7 +289,7 @@ impl<'a> From<&'a [Capability]> for Capabilities { } /// An extended externalities for offchain workers. -pub trait Externalities { +pub trait Externalities: Send { /// Returns if the local node is a potential validator. /// /// Even if this function returns `true`, it does not mean that any keys are configured diff --git a/core/state-machine/src/testing.rs b/core/state-machine/src/testing.rs index 16ff62020b594..8253f20c8bd01 100644 --- a/core/state-machine/src/testing.rs +++ b/core/state-machine/src/testing.rs @@ -192,4 +192,10 @@ mod tests { assert_eq!(&ext.storage(CODE).unwrap(), &code); } + + #[test] + fn check_send() { + fn assert_send() {} + assert_send::>(); + } }