|
| 1 | +// Test that slice subslice patterns are correctly handled in const evaluation. |
| 2 | + |
| 3 | +// run-pass |
| 4 | + |
| 5 | +#![feature(slice_patterns, const_fn, const_if_match)] |
| 6 | +#[derive(PartialEq, Debug, Clone)] |
| 7 | +struct N(u8); |
| 8 | + |
| 9 | +#[derive(PartialEq, Debug, Clone)] |
| 10 | +struct Z; |
| 11 | + |
| 12 | +macro_rules! n { |
| 13 | + ($($e:expr),* $(,)?) => { |
| 14 | + [$(N($e)),*] |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +// This macro has an unused variable so that it can be repeated base on the |
| 19 | +// number of times a repeated variable (`$e` in `z`) occurs. |
| 20 | +macro_rules! zed { |
| 21 | + ($e:expr) => { Z } |
| 22 | +} |
| 23 | + |
| 24 | +macro_rules! z { |
| 25 | + ($($e:expr),* $(,)?) => { |
| 26 | + [$(zed!($e)),*] |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +// Compare constant evaluation and runtime evaluation of a given expression. |
| 31 | +macro_rules! compare_evaluation_inner { |
| 32 | + ($e:expr, $t:ty $(,)?) => {{ |
| 33 | + const CONST_EVAL: $t = $e; |
| 34 | + const fn const_eval() -> $t { $e } |
| 35 | + static CONST_EVAL2: $t = const_eval(); |
| 36 | + let runtime_eval = $e; |
| 37 | + assert_eq!(CONST_EVAL, runtime_eval); |
| 38 | + assert_eq!(CONST_EVAL2, runtime_eval); |
| 39 | + }} |
| 40 | +} |
| 41 | + |
| 42 | +// Compare the result of matching `$e` against `$p` using both `if let` and |
| 43 | +// `match`. |
| 44 | +macro_rules! compare_evaluation { |
| 45 | + ($p:pat, $e:expr, $matches:expr, $t:ty $(,)?) => {{ |
| 46 | + compare_evaluation_inner!(if let $p = $e as &[_] { $matches } else { None }, $t); |
| 47 | + compare_evaluation_inner!(match $e as &[_] { $p => $matches, _ => None }, $t); |
| 48 | + }} |
| 49 | +} |
| 50 | + |
| 51 | +// Repeat `$test`, substituting the given macro variables with the given |
| 52 | +// identifiers. |
| 53 | +// |
| 54 | +// For example: |
| 55 | +// |
| 56 | +// repeat! { |
| 57 | +// ($name); X; Y: |
| 58 | +// struct $name; |
| 59 | +// } |
| 60 | +// |
| 61 | +// Expands to: |
| 62 | +// |
| 63 | +// struct X; struct Y; |
| 64 | +// |
| 65 | +// This is used to repeat the tests using both the `N` and `Z` |
| 66 | +// types. |
| 67 | +macro_rules! repeat { |
| 68 | + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { |
| 69 | + macro_rules! single { |
| 70 | + ($($dollar $placeholder:ident),*) => { $($test)* } |
| 71 | + } |
| 72 | + $(single!($($values),+);)* |
| 73 | + } |
| 74 | +} |
| 75 | + |
| 76 | +fn main() { |
| 77 | + repeat! { |
| 78 | + ($arr $Ty); n, N; z, Z: |
| 79 | + compare_evaluation!([_, x @ .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static [$Ty]>); |
| 80 | + compare_evaluation!([x, .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); |
| 81 | + compare_evaluation!([_, .., x], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); |
| 82 | + |
| 83 | + compare_evaluation!([_, x @ .., _], &$arr!(1, 2), Some(x), Option<&'static [$Ty]>); |
| 84 | + compare_evaluation!([x, .., _], &$arr!(1, 2), Some(x), Option<&'static $Ty>); |
| 85 | + compare_evaluation!([_, .., x], &$arr!(1, 2), Some(x), Option<&'static $Ty>); |
| 86 | + |
| 87 | + compare_evaluation!([_, x @ .., _], &$arr!(1), Some(x), Option<&'static [$Ty]>); |
| 88 | + compare_evaluation!([x, .., _], &$arr!(1), Some(x), Option<&'static $Ty>); |
| 89 | + compare_evaluation!([_, .., x], &$arr!(1), Some(x), Option<&'static $Ty>); |
| 90 | + } |
| 91 | + |
| 92 | + compare_evaluation!([N(x), .., _], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); |
| 93 | + compare_evaluation!([_, .., N(x)], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); |
| 94 | + |
| 95 | + compare_evaluation!([N(x), .., _], &n!(1, 2), Some(x), Option<&'static u8>); |
| 96 | + compare_evaluation!([_, .., N(x)], &n!(1, 2), Some(x), Option<&'static u8>); |
| 97 | +} |
0 commit comments