Skip to content

Commit 59dad41

Browse files
rodrimati1992fizyk20
authored andcommitted
Fixed lifetime unsoundness in arr macro.
Added doctests (that don't appear in the public documentation) for cases that are expected to compile,and not compile.
1 parent 1e96864 commit 59dad41

File tree

1 file changed

+74
-5
lines changed

1 file changed

+74
-5
lines changed

Diff for: src/arr.rs

+74-5
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,30 @@ pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
2525
#[doc(hidden)]
2626
#[macro_export]
2727
macro_rules! arr_impl {
28+
(@replace_expr $e:expr)=>{
29+
1
30+
};
2831
($T:ty; $N:ty, [$($x:expr),*], []) => ({
29-
unsafe { $crate::transmute::<_, $crate::GenericArray<$T, $N>>([$($x),*]) }
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),*])
3040
});
3141
($T:ty; $N:ty, [], [$x1:expr]) => (
32-
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [])
42+
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
3343
);
3444
($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
35-
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [$($x),+])
45+
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
3646
);
3747
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
38-
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [])
48+
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
3949
);
4050
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
41-
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [$($x),+])
51+
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+])
4252
);
4353
}
4454

@@ -55,3 +65,62 @@ macro_rules! arr {
5565
($($x:expr,)+) => (arr![$($x),*]);
5666
() => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
5767
}
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+
}

0 commit comments

Comments
 (0)