-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #67467 - matthewjasper:test-slice-patterns, r=oli-obk
Test slice patterns more Adds tests for const evaluation and some more borrow checking tests. Fixes some bugs in const eval for subslice patterns. closes #66934 r? @oli-obk cc @Centril
- Loading branch information
Showing
11 changed files
with
703 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Test that slice subslice patterns are correctly handled in const evaluation. | ||
|
||
// run-pass | ||
|
||
#![feature(slice_patterns, const_fn, const_if_match)] | ||
#[derive(PartialEq, Debug, Clone)] | ||
struct N(u8); | ||
|
||
#[derive(PartialEq, Debug, Clone)] | ||
struct Z; | ||
|
||
macro_rules! n { | ||
($($e:expr),* $(,)?) => { | ||
[$(N($e)),*] | ||
} | ||
} | ||
|
||
// This macro has an unused variable so that it can be repeated base on the | ||
// number of times a repeated variable (`$e` in `z`) occurs. | ||
macro_rules! zed { | ||
($e:expr) => { Z } | ||
} | ||
|
||
macro_rules! z { | ||
($($e:expr),* $(,)?) => { | ||
[$(zed!($e)),*] | ||
} | ||
} | ||
|
||
// Compare constant evaluation and runtime evaluation of a given expression. | ||
macro_rules! compare_evaluation_inner { | ||
($e:expr, $t:ty $(,)?) => {{ | ||
const CONST_EVAL: $t = $e; | ||
const fn const_eval() -> $t { $e } | ||
static CONST_EVAL2: $t = const_eval(); | ||
let runtime_eval = $e; | ||
assert_eq!(CONST_EVAL, runtime_eval); | ||
assert_eq!(CONST_EVAL2, runtime_eval); | ||
}} | ||
} | ||
|
||
// Compare the result of matching `$e` against `$p` using both `if let` and | ||
// `match`. | ||
macro_rules! compare_evaluation { | ||
($p:pat, $e:expr, $matches:expr, $t:ty $(,)?) => {{ | ||
compare_evaluation_inner!(if let $p = $e as &[_] { $matches } else { None }, $t); | ||
compare_evaluation_inner!(match $e as &[_] { $p => $matches, _ => None }, $t); | ||
}} | ||
} | ||
|
||
// Repeat `$test`, substituting the given macro variables with the given | ||
// identifiers. | ||
// | ||
// For example: | ||
// | ||
// repeat! { | ||
// ($name); X; Y: | ||
// struct $name; | ||
// } | ||
// | ||
// Expands to: | ||
// | ||
// struct X; struct Y; | ||
// | ||
// This is used to repeat the tests using both the `N` and `Z` | ||
// types. | ||
macro_rules! repeat { | ||
(($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { | ||
macro_rules! single { | ||
($($dollar $placeholder:ident),*) => { $($test)* } | ||
} | ||
$(single!($($values),+);)* | ||
} | ||
} | ||
|
||
fn main() { | ||
repeat! { | ||
($arr $Ty); n, N; z, Z: | ||
compare_evaluation!([_, x @ .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static [$Ty]>); | ||
compare_evaluation!([x, .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); | ||
compare_evaluation!([_, .., x], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); | ||
|
||
compare_evaluation!([_, x @ .., _], &$arr!(1, 2), Some(x), Option<&'static [$Ty]>); | ||
compare_evaluation!([x, .., _], &$arr!(1, 2), Some(x), Option<&'static $Ty>); | ||
compare_evaluation!([_, .., x], &$arr!(1, 2), Some(x), Option<&'static $Ty>); | ||
|
||
compare_evaluation!([_, x @ .., _], &$arr!(1), Some(x), Option<&'static [$Ty]>); | ||
compare_evaluation!([x, .., _], &$arr!(1), Some(x), Option<&'static $Ty>); | ||
compare_evaluation!([_, .., x], &$arr!(1), Some(x), Option<&'static $Ty>); | ||
} | ||
|
||
compare_evaluation!([N(x), .., _], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); | ||
compare_evaluation!([_, .., N(x)], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); | ||
|
||
compare_evaluation!([N(x), .., _], &n!(1, 2), Some(x), Option<&'static u8>); | ||
compare_evaluation!([_, .., N(x)], &n!(1, 2), Some(x), Option<&'static u8>); | ||
} |
97 changes: 97 additions & 0 deletions
97
src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Test that array subslice patterns are correctly handled in const evaluation. | ||
|
||
// run-pass | ||
|
||
#![feature(slice_patterns)] | ||
|
||
#[derive(PartialEq, Debug, Clone)] | ||
struct N(u8); | ||
|
||
#[derive(PartialEq, Debug, Clone)] | ||
struct Z; | ||
|
||
macro_rules! n { | ||
($($e:expr),* $(,)?) => { | ||
[$(N($e)),*] | ||
} | ||
} | ||
|
||
// This macro has an unused variable so that it can be repeated base on the | ||
// number of times a repeated variable (`$e` in `z`) occurs. | ||
macro_rules! zed { | ||
($e:expr) => { Z } | ||
} | ||
|
||
macro_rules! z { | ||
($($e:expr),* $(,)?) => { | ||
[$(zed!($e)),*] | ||
} | ||
} | ||
|
||
// Compare constant evaluation and runtime evaluation of a given expression. | ||
macro_rules! compare_evaluation { | ||
($e:expr, $t:ty $(,)?) => {{ | ||
const CONST_EVAL: $t = $e; | ||
const fn const_eval() -> $t { $e } | ||
static CONST_EVAL2: $t = const_eval(); | ||
let runtime_eval = $e; | ||
assert_eq!(CONST_EVAL, runtime_eval); | ||
assert_eq!(CONST_EVAL2, runtime_eval); | ||
}} | ||
} | ||
|
||
// Repeat `$test`, substituting the given macro variables with the given | ||
// identifiers. | ||
// | ||
// For example: | ||
// | ||
// repeat! { | ||
// ($name); X; Y: | ||
// struct $name; | ||
// } | ||
// | ||
// Expands to: | ||
// | ||
// struct X; struct Y; | ||
// | ||
// This is used to repeat the tests using both the `N` and `Z` | ||
// types. | ||
macro_rules! repeat { | ||
(($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { | ||
macro_rules! single { | ||
($($dollar $placeholder:ident),*) => { $($test)* } | ||
} | ||
$(single!($($values),+);)* | ||
} | ||
} | ||
|
||
fn main() { | ||
repeat! { | ||
($arr $Ty); n, N; z, Z: | ||
compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]); | ||
compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); | ||
compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); | ||
|
||
compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]); | ||
compare_evaluation!( | ||
{ let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x }, | ||
&'static [$Ty; 0], | ||
); | ||
compare_evaluation!( | ||
{ let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x }, | ||
&'static [$Ty; 0], | ||
); | ||
|
||
compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty); | ||
compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty); | ||
compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty); | ||
} | ||
|
||
compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8); | ||
compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8); | ||
compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8); | ||
|
||
compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8); | ||
compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8); | ||
compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8); | ||
} |
118 changes: 118 additions & 0 deletions
118
src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Check that closure captures for slice patterns are inferred correctly | ||
|
||
#![feature(slice_patterns)] | ||
#![allow(unused_variables)] | ||
|
||
// run-pass | ||
|
||
fn arr_by_ref(x: [String; 3]) { | ||
let r = &x; | ||
let f = || { | ||
let [ref y, ref z @ ..] = x; | ||
}; | ||
f(); | ||
f(); | ||
// Ensure `x` was borrowed | ||
drop(r); | ||
// Ensure that `x` wasn't moved from. | ||
drop(x); | ||
} | ||
|
||
fn arr_by_mut(mut x: [String; 3]) { | ||
let mut f = || { | ||
let [ref mut y, ref mut z @ ..] = x; | ||
}; | ||
f(); | ||
f(); | ||
drop(x); | ||
} | ||
|
||
fn arr_by_move(x: [String; 3]) { | ||
let f = || { | ||
let [y, z @ ..] = x; | ||
}; | ||
f(); | ||
} | ||
|
||
fn arr_ref_by_ref(x: &[String; 3]) { | ||
let r = &x; | ||
let f = || { | ||
let [ref y, ref z @ ..] = *x; | ||
}; | ||
let g = || { | ||
let [y, z @ ..] = x; | ||
}; | ||
f(); | ||
g(); | ||
f(); | ||
g(); | ||
drop(r); | ||
drop(x); | ||
} | ||
|
||
fn arr_ref_by_mut(x: &mut [String; 3]) { | ||
let mut f = || { | ||
let [ref mut y, ref mut z @ ..] = *x; | ||
}; | ||
f(); | ||
f(); | ||
let mut g = || { | ||
let [y, z @ ..] = x; | ||
// Ensure binding mode was chosen correctly: | ||
std::mem::swap(y, &mut z[0]); | ||
}; | ||
g(); | ||
g(); | ||
drop(x); | ||
} | ||
|
||
fn arr_box_by_move(x: Box<[String; 3]>) { | ||
let f = || { | ||
let [y, z @ ..] = *x; | ||
}; | ||
f(); | ||
} | ||
|
||
fn slice_by_ref(x: &[String]) { | ||
let r = &x; | ||
let f = || { | ||
if let [ref y, ref z @ ..] = *x {} | ||
}; | ||
let g = || { | ||
if let [y, z @ ..] = x {} | ||
}; | ||
f(); | ||
g(); | ||
f(); | ||
g(); | ||
drop(r); | ||
drop(x); | ||
} | ||
|
||
fn slice_by_mut(x: &mut [String]) { | ||
let mut f = || { | ||
if let [ref mut y, ref mut z @ ..] = *x {} | ||
}; | ||
f(); | ||
f(); | ||
let mut g = || { | ||
if let [y, z @ ..] = x { | ||
// Ensure binding mode was chosen correctly: | ||
std::mem::swap(y, &mut z[0]); | ||
} | ||
}; | ||
g(); | ||
g(); | ||
drop(x); | ||
} | ||
|
||
fn main() { | ||
arr_by_ref(Default::default()); | ||
arr_by_mut(Default::default()); | ||
arr_by_move(Default::default()); | ||
arr_ref_by_ref(&Default::default()); | ||
arr_ref_by_mut(&mut Default::default()); | ||
arr_box_by_move(Default::default()); | ||
slice_by_ref(&<[_; 3]>::default()); | ||
slice_by_mut(&mut <[_; 3]>::default()); | ||
} |
Oops, something went wrong.