From 32cec9ba8706bcb24140de689e7459d8add0d325 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 12 Jul 2018 17:43:18 +0200 Subject: [PATCH] environmental! handles generics (#307) * Teach environmental! about generics * whitespace --- substrate/environmental/src/lib.rs | 43 ++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 86e1100ecccad..ff94c0c1ebbb0 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -190,33 +190,36 @@ macro_rules! environmental { } } }; - ($name:ident : trait $t:ident) => { - #[allow(non_camel_case_types)] + ($name:ident : trait @$t:ident [$($args:ty,)*]) => { + #[allow(non_camel_case_types, dead_code)] struct $name { __private_field: () } - thread_local_impl!(static GLOBAL: $crate::imp::RefCell> + thread_local_impl!(static GLOBAL: $crate::imp::RefCell + 'static)>> = $crate::imp::RefCell::new(None)); impl $name { - #[allow(unused_imports)] + #[allow(unused_imports)] pub fn using R>( - protected: &mut $t, + protected: &mut $t<$($args),*>, f: F ) -> R { let lifetime_extended = unsafe { - $crate::imp::transmute::<&mut $t, &mut ($t + 'static)>(protected) + $crate::imp::transmute::<&mut $t<$($args),*>, &mut ($t<$($args),*> + 'static)>(protected) }; $crate::using(&GLOBAL, lifetime_extended, f) } - pub fn with FnOnce(&'a mut ($t + 'a)) -> R>( + pub fn with FnOnce(&'a mut ($t<$($args),*> + 'a)) -> R>( f: F ) -> Option { $crate::with(&GLOBAL, |x| f(x)) } } - } + }; + ($name:ident : trait $t:ident <>) => { environmental! { $name : trait @$t [] } }; + ($name:ident : trait $t:ident < $($args:ty),* $(,)* >) => { environmental! { $name : trait @$t [$($args,)*] } }; + ($name:ident : trait $t:ident) => { environmental! { $name : trait @$t [] } }; } #[cfg(test)] @@ -322,4 +325,28 @@ mod tests { assert_eq!(got_sum, 15); } + + #[test] + fn use_generic_trait() { + trait Plus { fn plus42() -> usize; } + struct ConcretePlus; + impl Plus for ConcretePlus { + fn plus42() -> usize { 42 } + } + trait Multiplier { fn mul_and_add(&self) -> usize; } + impl<'a, P: Plus> Multiplier

for &'a [usize] { + fn mul_and_add(&self) -> usize { + self.iter().fold(1, |a, c| a * c) + P::plus42() + } + } + + let numbers = vec![1, 2, 3]; + let mut numbers = &numbers[..]; + let out = foo::using(&mut numbers, || { + foo::with(|x| x.mul_and_add() ) + }).unwrap(); + + assert_eq!(out, 6 + 42); + environmental!(foo: trait Multiplier); + } }