diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index ef5b5967bea9f38c69b698159e779fea09c966f7..1b9587a5a53900350818c43a47c10b9e68a6b1b5 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -183,6 +183,33 @@ macro_rules! environmental { } } }; + ($name:ident : trait $t:ident) => { + #[allow(non_camel_case_types)] + struct $name { __private_field: () } + + thread_local!(static GLOBAL: ::std::cell::RefCell<Option<*mut ($t + 'static)>> + = ::std::cell::RefCell::new(None)); + + impl $name { + #[allow(unused_imports)] + + pub fn using<R, F: FnOnce() -> R>( + protected: &mut $t, + f: F + ) -> R { + let lifetime_extended = unsafe { + ::std::mem::transmute::<&mut $t, &mut ($t + 'static)>(protected) + }; + $crate::using(&GLOBAL, lifetime_extended, f) + } + + pub fn with<R, F: for<'a> FnOnce(&'a mut ($t + 'a)) -> R>( + f: F + ) -> Option<R> { + $crate::with(&GLOBAL, |x| f(x)) + } + } + } } #[cfg(test)] @@ -269,4 +296,23 @@ mod tests { assert!(was_cleared); } + + #[test] + fn use_non_static_trait() { + trait Sum { fn sum(&self) -> usize; } + impl<'a> Sum for &'a [usize] { + fn sum(&self) -> usize { + self.iter().fold(0, |a, c| a + c) + } + } + + environmental!(sum: trait Sum); + let numbers = vec![1, 2, 3, 4, 5]; + let mut numbers = &numbers[..]; + let got_sum = sum::using(&mut numbers, || { + sum::with(|x| x.sum()) + }).unwrap(); + + assert_eq!(got_sum, 15); + } } diff --git a/substrate/wasm-runtime/polkadot/src/support/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs index c01a1f4e928237fdd482820e44003fabfc3aeb96..02c29afc1bf69f7394ddf47d43ea50ee9687cb91 100644 --- a/substrate/wasm-runtime/polkadot/src/support/environment.rs +++ b/substrate/wasm-runtime/polkadot/src/support/environment.rs @@ -37,7 +37,7 @@ pub fn with_env<T, F: FnOnce(&mut Environment) -> T>(f: F) -> T { f(&mut *eb) } -#[cfg(not(test))] +#[cfg(target_arch = "wasm32")] fn env() -> Rc<RefCell<Environment>> { // Initialize it to a null value static mut SINGLETON: *const Rc<RefCell<Environment>> = 0 as *const Rc<RefCell<Environment>>; @@ -56,7 +56,7 @@ fn env() -> Rc<RefCell<Environment>> { } } -#[cfg(test)] +#[cfg(not(target_arch = "wasm32"))] fn env() -> Rc<RefCell<Environment>> { // Initialize it to a null value thread_local!{