1 //! Implementation for `arr!` macro. 2 3 use super::ArrayLength; 4 use core::ops::Add; 5 use typenum::U1; 6 7 /// Helper trait for `arr!` macro 8 pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> { 9 /// Resulting length 10 type Output: ArrayLength<T>; 11 } 12 13 impl<T, N1, N2> AddLength<T, N2> for N1 14 where 15 N1: ArrayLength<T> + Add<N2>, 16 N2: ArrayLength<T>, 17 <N1 as Add<N2>>::Output: ArrayLength<T>, 18 { 19 type Output = <N1 as Add<N2>>::Output; 20 } 21 22 /// Helper type for `arr!` macro 23 pub type Inc<T, U> = <U as AddLength<T, U1>>::Output; 24 25 #[doc(hidden)] 26 #[macro_export] 27 macro_rules! arr_impl { 28 (@replace_expr $e:expr)=>{ 29 1 30 }; 31 ($T:ty; $N:ty, [$($x:expr),*], []) => ({ 32 const __ARR_LENGTH:usize=0 $(+ $crate::arr_impl!(@replace_expr $x) )*; 33 fn __do_transmute<'a, T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> { 34 unsafe { $crate::transmute(arr) } 35 } 36 37 let _:[();<$N as $crate::typenum::Unsigned>::USIZE]=[();__ARR_LENGTH]; 38 39 __do_transmute::<$T,$N>([$($x),*]) 40 }); 41 ($T:ty; $N:ty, [], [$x1:expr]) => ( 42 $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], []) 43 ); 44 ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => ( 45 $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+]) 46 ); 47 ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => ( 48 $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], []) 49 ); 50 ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => ( 51 $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+]) 52 ); 53 } 54 55 /// Macro allowing for easy generation of Generic Arrays. 56 /// Example: `let test = arr![u32; 1, 2, 3];` 57 #[macro_export] 58 macro_rules! arr { 59 ($T:ty; $(,)*) => ({ 60 unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) } 61 }); 62 ($T:ty; $($x:expr),* $(,)*) => ( 63 arr_impl!($T; $crate::typenum::U0, [], [$($x),*]) 64 ); 65 ($($x:expr,)+) => (arr![$($x),*]); 66 () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`") 67 } 68 69 70 mod doctests_only{ 71 /// 72 /// # With ellision 73 /// 74 /// Testing that lifetimes aren't transmuted when they're ellided. 75 /// 76 /// ```compile_fail 77 /// #[macro_use] extern crate generic_array; 78 /// fn main() { 79 /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A { 80 /// arr![&A; a][0] 81 /// } 82 /// } 83 /// ``` 84 /// 85 /// ```rust 86 /// #[macro_use] extern crate generic_array; 87 /// fn main() { 88 /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A { 89 /// arr![&A; a][0] 90 /// } 91 /// } 92 /// ``` 93 /// 94 /// # Without ellision 95 /// 96 /// Testing that lifetimes aren't transmuted when they're specified explicitly. 97 /// 98 /// ```compile_fail 99 /// #[macro_use] extern crate generic_array; 100 /// fn main() { 101 /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A { 102 /// arr![&'a A; a][0] 103 /// } 104 /// } 105 /// ``` 106 /// 107 /// ```compile_fail 108 /// #[macro_use] extern crate generic_array; 109 /// fn main() { 110 /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A { 111 /// arr![&'static A; a][0] 112 /// } 113 /// } 114 /// ``` 115 /// 116 /// ```rust 117 /// #[macro_use] extern crate generic_array; 118 /// fn main() { 119 /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A { 120 /// arr![&'a A; a][0] 121 /// } 122 /// } 123 /// ``` 124 #[allow(dead_code)] 125 pub enum DocTests{} 126 } 127