From a34f6144dcef175116f2b5c049140d7b396b38a7 Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 12 Jul 2018 16:28:11 +0200 Subject: [PATCH 1/2] Teach environmental! about generics --- substrate/environmental/src/lib.rs | 51 +++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 86e1100ecccad..83be99f278f41 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)] - struct $name { __private_field: () } + ($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)] + impl $name { + #[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); + } } From 711da4f1dd255c5d07ed4864a31004a4aefdea76 Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 12 Jul 2018 17:15:07 +0200 Subject: [PATCH 2/2] whitespace --- substrate/environmental/src/lib.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 83be99f278f41..ff94c0c1ebbb0 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -190,15 +190,15 @@ macro_rules! environmental { } } }; - ($name:ident : trait @$t:ident [$($args:ty,)*]) => { - #[allow(non_camel_case_types, dead_code)] - struct $name { __private_field: () } + ($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 + 'static)>> = $crate::imp::RefCell::new(None)); - impl $name { - #[allow(unused_imports)] + impl $name { + #[allow(unused_imports)] pub fn using R>( protected: &mut $t<$($args),*>, @@ -208,18 +208,18 @@ macro_rules! environmental { $crate::imp::transmute::<&mut $t<$($args),*>, &mut ($t<$($args),*> + 'static)>(protected) }; $crate::using(&GLOBAL, lifetime_extended, f) - } + } 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 [] } }; + } + }; + ($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)]