Skip to content

Commit

Permalink
Fixed lifetime unsoundness in arr macro.
Browse files Browse the repository at this point in the history
Added doctests (that don't appear in the public documentation) for cases that
are expected to compile,and not compile.
  • Loading branch information
rodrimati1992 authored and fizyk20 committed Mar 2, 2021
1 parent 1e96864 commit 59dad41
Showing 1 changed file with 74 additions and 5 deletions.
79 changes: 74 additions & 5 deletions src/arr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,30 @@ pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
#[doc(hidden)]
#[macro_export]
macro_rules! arr_impl {
(@replace_expr $e:expr)=>{
1
};
($T:ty; $N:ty, [$($x:expr),*], []) => ({
unsafe { $crate::transmute::<_, $crate::GenericArray<$T, $N>>([$($x),*]) }
const __ARR_LENGTH:usize=0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
fn __do_transmute<'a, T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {
unsafe { $crate::transmute(arr) }
}

let _:[();<$N as $crate::typenum::Unsigned>::USIZE]=[();__ARR_LENGTH];

__do_transmute::<$T,$N>([$($x),*])
});
($T:ty; $N:ty, [], [$x1:expr]) => (
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [])
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
);
($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [$($x),+])
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
);
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [])
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
);
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [$($x),+])
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+])
);
}

Expand All @@ -55,3 +65,62 @@ macro_rules! arr {
($($x:expr,)+) => (arr![$($x),*]);
() => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
}


mod doctests_only{
///
/// # With ellision
///
/// Testing that lifetimes aren't transmuted when they're ellided.
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&A; a][0]
/// }
/// }
/// ```
///
/// ```rust
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
/// arr![&A; a][0]
/// }
/// }
/// ```
///
/// # Without ellision
///
/// Testing that lifetimes aren't transmuted when they're specified explicitly.
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&'a A; a][0]
/// }
/// }
/// ```
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&'static A; a][0]
/// }
/// }
/// ```
///
/// ```rust
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
/// arr![&'a A; a][0]
/// }
/// }
/// ```
#[allow(dead_code)]
pub enum DocTests{}
}

0 comments on commit 59dad41

Please sign in to comment.