mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Add more tests for or-patterns
This commit is contained in:
parent
0b1ff27cd8
commit
c7e6f88926
76
src/test/mir-opt/exponential-or.rs
Normal file
76
src/test/mir-opt/exponential-or.rs
Normal file
@ -0,0 +1,76 @@
|
||||
// Test that simple or-patterns don't get expanded to exponentially large CFGs
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn match_tuple(x: (u32, bool, Option<i32>, u32)) -> u32 {
|
||||
match x {
|
||||
(y @ (1 | 4), true | false, Some(1 | 8) | None, z @ (6..=9 | 13..=16)) => y ^ z,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
// END RUST SOURCE
|
||||
|
||||
// START rustc.match_tuple.SimplifyCfg-initial.after.mir
|
||||
// scope 1 {
|
||||
// debug y => _7;
|
||||
// debug z => _8;
|
||||
// }
|
||||
// bb0: {
|
||||
// FakeRead(ForMatchedPlace, _1);
|
||||
// switchInt((_1.0: u32)) -> [1u32: bb2, 4u32: bb2, otherwise: bb1];
|
||||
// }
|
||||
// bb1: {
|
||||
// _0 = const 0u32;
|
||||
// goto -> bb10;
|
||||
// }
|
||||
// bb2: {
|
||||
// _2 = discriminant((_1.2: std::option::Option<i32>));
|
||||
// switchInt(move _2) -> [0isize: bb4, 1isize: bb3, otherwise: bb1];
|
||||
// }
|
||||
// bb3: {
|
||||
// switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1i32: bb4, 8i32: bb4, otherwise: bb1];
|
||||
// }
|
||||
// bb4: {
|
||||
// _5 = Le(const 6u32, (_1.3: u32));
|
||||
// switchInt(move _5) -> [false: bb6, otherwise: bb5];
|
||||
// }
|
||||
// bb5: {
|
||||
// _6 = Le((_1.3: u32), const 9u32);
|
||||
// switchInt(move _6) -> [false: bb6, otherwise: bb8];
|
||||
// }
|
||||
// bb6: {
|
||||
// _3 = Le(const 13u32, (_1.3: u32));
|
||||
// switchInt(move _3) -> [false: bb1, otherwise: bb7];
|
||||
// }
|
||||
// bb7: {
|
||||
// _4 = Le((_1.3: u32), const 16u32);
|
||||
// switchInt(move _4) -> [false: bb1, otherwise: bb8];
|
||||
// }
|
||||
// bb8: {
|
||||
// falseEdges -> [real: bb9, imaginary: bb1];
|
||||
// }
|
||||
// bb9: {
|
||||
// StorageLive(_7);
|
||||
// _7 = (_1.0: u32);
|
||||
// StorageLive(_8);
|
||||
// _8 = (_1.3: u32);
|
||||
// StorageLive(_9);
|
||||
// _9 = _7;
|
||||
// StorageLive(_10);
|
||||
// _10 = _8;
|
||||
// _0 = BitXor(move _9, move _10);
|
||||
// StorageDead(_10);
|
||||
// StorageDead(_9);
|
||||
// StorageDead(_8);
|
||||
// StorageDead(_7);
|
||||
// goto -> bb10;
|
||||
// }
|
||||
// bb10: {
|
||||
// return;
|
||||
// }
|
||||
// END rustc.match_tuple.SimplifyCfg-initial.after.mir
|
64
src/test/ui/borrowck/or-patterns.rs
Normal file
64
src/test/ui/borrowck/or-patterns.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// Test that borrow check considers all choices in an or pattern, even the
|
||||
// unreachable ones.
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn or_pattern_moves_all(x: ((String, String),)) {
|
||||
match x {
|
||||
((y, _) | (_, y),) => (),
|
||||
}
|
||||
&x.0 .0;
|
||||
//~^ ERROR borrow of moved value
|
||||
&x.0 .1;
|
||||
//~^ ERROR borrow of moved value
|
||||
}
|
||||
|
||||
fn or_pattern_borrows_all(mut x: ((String, String),)) {
|
||||
let r = match x {
|
||||
((ref y, _) | (_, ref y),) => y,
|
||||
};
|
||||
&mut x.0 .0;
|
||||
//~^ ERROR cannot borrow
|
||||
&mut x.0 .1;
|
||||
//~^ ERROR cannot borrow
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn or_pattern_borrows_all_mut(mut x: ((String, String),)) {
|
||||
let r = match x {
|
||||
((ref mut y, _) | (_, ref mut y),) => y,
|
||||
};
|
||||
&x.0 .0;
|
||||
//~^ ERROR cannot borrow
|
||||
&x.0 .1;
|
||||
//~^ ERROR cannot borrow
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn let_or_pattern_moves_all(x: ((String, String),)) {
|
||||
let ((y, _) | (_, y),) = x;
|
||||
&x.0 .0;
|
||||
//~^ ERROR borrow of moved value
|
||||
&x.0 .1;
|
||||
//~^ ERROR borrow of moved value
|
||||
}
|
||||
|
||||
fn let_or_pattern_borrows_all(mut x: ((String, String),)) {
|
||||
let ((ref r, _) | (_, ref r),) = x;
|
||||
&mut x.0 .0;
|
||||
//~^ ERROR cannot borrow
|
||||
&mut x.0 .1;
|
||||
//~^ ERROR cannot borrow
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn let_or_pattern_borrows_all_mut(mut x: ((String, String),)) {
|
||||
let ((ref mut r, _) | (_, ref mut r),) = x;
|
||||
&x.0 .0;
|
||||
//~^ ERROR cannot borrow
|
||||
&x.0 .1;
|
||||
//~^ ERROR cannot borrow
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn main() {}
|
141
src/test/ui/borrowck/or-patterns.stderr
Normal file
141
src/test/ui/borrowck/or-patterns.stderr
Normal file
@ -0,0 +1,141 @@
|
||||
error[E0382]: borrow of moved value: `x.0.0`
|
||||
--> $DIR/or-patterns.rs:10:5
|
||||
|
|
||||
LL | ((y, _) | (_, y),) => (),
|
||||
| - value moved here
|
||||
LL | }
|
||||
LL | &x.0 .0;
|
||||
| ^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: move occurs because `x.0.0` has type `std::string::String`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value: `x.0.1`
|
||||
--> $DIR/or-patterns.rs:12:5
|
||||
|
|
||||
LL | ((y, _) | (_, y),) => (),
|
||||
| - value moved here
|
||||
...
|
||||
LL | &x.0 .1;
|
||||
| ^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: move occurs because `x.0.1` has type `std::string::String`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/or-patterns.rs:20:5
|
||||
|
|
||||
LL | ((ref y, _) | (_, ref y),) => y,
|
||||
| ----- immutable borrow occurs here
|
||||
LL | };
|
||||
LL | &mut x.0 .0;
|
||||
| ^^^^^^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/or-patterns.rs:22:5
|
||||
|
|
||||
LL | ((ref y, _) | (_, ref y),) => y,
|
||||
| ----- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x.0 .1;
|
||||
| ^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL |
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/or-patterns.rs:31:5
|
||||
|
|
||||
LL | ((ref mut y, _) | (_, ref mut y),) => y,
|
||||
| --------- mutable borrow occurs here
|
||||
LL | };
|
||||
LL | &x.0 .0;
|
||||
| ^^^^^^^ immutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/or-patterns.rs:33:5
|
||||
|
|
||||
LL | ((ref mut y, _) | (_, ref mut y),) => y,
|
||||
| --------- mutable borrow occurs here
|
||||
...
|
||||
LL | &x.0 .1;
|
||||
| ^^^^^^^ immutable borrow occurs here
|
||||
LL |
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0382]: borrow of moved value: `x.0.0`
|
||||
--> $DIR/or-patterns.rs:40:5
|
||||
|
|
||||
LL | let ((y, _) | (_, y),) = x;
|
||||
| - value moved here
|
||||
LL | &x.0 .0;
|
||||
| ^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: move occurs because `x.0.0` has type `std::string::String`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value: `x.0.1`
|
||||
--> $DIR/or-patterns.rs:42:5
|
||||
|
|
||||
LL | let ((y, _) | (_, y),) = x;
|
||||
| - value moved here
|
||||
...
|
||||
LL | &x.0 .1;
|
||||
| ^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: move occurs because `x.0.1` has type `std::string::String`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/or-patterns.rs:48:5
|
||||
|
|
||||
LL | let ((ref r, _) | (_, ref r),) = x;
|
||||
| ----- immutable borrow occurs here
|
||||
LL | &mut x.0 .0;
|
||||
| ^^^^^^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/or-patterns.rs:50:5
|
||||
|
|
||||
LL | let ((ref r, _) | (_, ref r),) = x;
|
||||
| ----- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x.0 .1;
|
||||
| ^^^^^^^^^^^ mutable borrow occurs here
|
||||
LL |
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/or-patterns.rs:57:5
|
||||
|
|
||||
LL | let ((ref mut r, _) | (_, ref mut r),) = x;
|
||||
| --------- mutable borrow occurs here
|
||||
LL | &x.0 .0;
|
||||
| ^^^^^^^ immutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/or-patterns.rs:59:5
|
||||
|
|
||||
LL | let ((ref mut r, _) | (_, ref mut r),) = x;
|
||||
| --------- mutable borrow occurs here
|
||||
...
|
||||
LL | &x.0 .1;
|
||||
| ^^^^^^^ immutable borrow occurs here
|
||||
LL |
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0502.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
25
src/test/ui/or-patterns/bindings-runpass-1.rs
Normal file
25
src/test/ui/or-patterns/bindings-runpass-1.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn two_bindings(x: &((bool, bool), u8)) -> u8 {
|
||||
match x {
|
||||
&((true, y) | (y, true), z @ (0 | 4)) => (y as u8) + z,
|
||||
_ => 20,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(two_bindings(&((false, false), 0)), 20);
|
||||
assert_eq!(two_bindings(&((false, true), 0)), 0);
|
||||
assert_eq!(two_bindings(&((true, false), 0)), 0);
|
||||
assert_eq!(two_bindings(&((true, true), 0)), 1);
|
||||
assert_eq!(two_bindings(&((false, false), 4)), 20);
|
||||
assert_eq!(two_bindings(&((false, true), 4)), 4);
|
||||
assert_eq!(two_bindings(&((true, false), 4)), 4);
|
||||
assert_eq!(two_bindings(&((true, true), 4)), 5);
|
||||
assert_eq!(two_bindings(&((false, false), 3)), 20);
|
||||
assert_eq!(two_bindings(&((false, true), 3)), 20);
|
||||
assert_eq!(two_bindings(&((true, false), 3)), 20);
|
||||
assert_eq!(two_bindings(&((true, true), 3)), 20);
|
||||
}
|
32
src/test/ui/or-patterns/bindings-runpass-2.rs
Normal file
32
src/test/ui/or-patterns/bindings-runpass-2.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn or_at(x: Result<u32, u32>) -> u32 {
|
||||
match x {
|
||||
Ok(x @ 4) | Err(x @ (6 | 8)) => x,
|
||||
Ok(x @ 1 | x @ 2) => x,
|
||||
Err(x @ (0..=10 | 30..=40)) if x % 2 == 0 => x + 100,
|
||||
Err(x @ 0..=40) => x + 200,
|
||||
_ => 500,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(or_at(Ok(1)), 1);
|
||||
assert_eq!(or_at(Ok(2)), 2);
|
||||
assert_eq!(or_at(Ok(3)), 500);
|
||||
assert_eq!(or_at(Ok(4)), 4);
|
||||
assert_eq!(or_at(Ok(5)), 500);
|
||||
assert_eq!(or_at(Ok(6)), 500);
|
||||
assert_eq!(or_at(Err(1)), 201);
|
||||
assert_eq!(or_at(Err(2)), 102);
|
||||
assert_eq!(or_at(Err(3)), 203);
|
||||
assert_eq!(or_at(Err(4)), 104);
|
||||
assert_eq!(or_at(Err(5)), 205);
|
||||
assert_eq!(or_at(Err(6)), 6);
|
||||
assert_eq!(or_at(Err(7)), 207);
|
||||
assert_eq!(or_at(Err(8)), 8);
|
||||
assert_eq!(or_at(Err(20)), 220);
|
||||
assert_eq!(or_at(Err(50)), 500);
|
||||
}
|
18
src/test/ui/or-patterns/for-loop.rs
Normal file
18
src/test/ui/or-patterns/for-loop.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Check that or patterns are lowered correctly in `for` loops.
|
||||
// run-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn main() {
|
||||
let v = vec![Ok(2), Err(3), Ok(5)];
|
||||
let mut w = Vec::new();
|
||||
for &(Ok(i) | Err(i)) in &v {
|
||||
w.push(i);
|
||||
}
|
||||
let mut u = Vec::new();
|
||||
for Ok(i) | Err(i) in v {
|
||||
u.push(i);
|
||||
}
|
||||
assert_eq!(w, [2, 3, 5]);
|
||||
assert_eq!(u, [2, 3, 5]);
|
||||
}
|
22
src/test/ui/or-patterns/if-let-while-let.rs
Normal file
22
src/test/ui/or-patterns/if-let-while-let.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Check that or patterns are lowered correctly in `if let` and `while let` expressions.
|
||||
// run-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn main() {
|
||||
let mut opt = Some(3);
|
||||
let mut w = Vec::new();
|
||||
while let Some(ref mut val @ (3 | 4 | 6)) = opt {
|
||||
w.push(*val);
|
||||
*val += 1;
|
||||
}
|
||||
assert_eq!(w, [3, 4]);
|
||||
if let &(None | Some(6 | 7)) = &opt {
|
||||
unreachable!();
|
||||
}
|
||||
if let Some(x @ (4 | 5 | 6)) = opt {
|
||||
assert_eq!(x, 5);
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
11
src/test/ui/or-patterns/issue-67514-irrefutable-param.rs
Normal file
11
src/test/ui/or-patterns/issue-67514-irrefutable-param.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Check that we don't ICE for irrefutable or-patterns in function parameters
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
fn foo((Some(_) | None): Option<u32>) {}
|
||||
|
||||
fn main() {
|
||||
foo(None);
|
||||
}
|
19
src/test/ui/or-patterns/let-pattern.rs
Normal file
19
src/test/ui/or-patterns/let-pattern.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![feature(or_patterns)]
|
||||
|
||||
// run-pass
|
||||
|
||||
fn or_pat_let(x: Result<u32, u32>) -> u32 {
|
||||
let Ok(y) | Err(y) = x;
|
||||
y
|
||||
}
|
||||
|
||||
fn or_pat_arg((Ok(y) | Err(y)): Result<u32, u32>) -> u32 {
|
||||
y
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(or_pat_let(Ok(3)), 3);
|
||||
assert_eq!(or_pat_let(Err(5)), 5);
|
||||
assert_eq!(or_pat_arg(Ok(7)), 7);
|
||||
assert_eq!(or_pat_arg(Err(9)), 9);
|
||||
}
|
66
src/test/ui/or-patterns/search-via-bindings.rs
Normal file
66
src/test/ui/or-patterns/search-via-bindings.rs
Normal file
@ -0,0 +1,66 @@
|
||||
// Check that we expand multiple or-patterns from left to right.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
#![allow(unreachable_patterns)] // FIXME(or-patterns) this shouldn't trigger
|
||||
|
||||
fn search(target: (bool, bool, bool)) -> u32 {
|
||||
let x = ((false, true), (false, true), (false, true));
|
||||
let mut guard_count = 0;
|
||||
match x {
|
||||
((a, _) | (_, a), (b @ _, _) | (_, b @ _), (c @ false, _) | (_, c @ true))
|
||||
if {
|
||||
guard_count += 1;
|
||||
(a, b, c) == target
|
||||
} =>
|
||||
{
|
||||
guard_count
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent to the above code, but hopefully easier to understand.
|
||||
fn search_old_style(target: (bool, bool, bool)) -> u32 {
|
||||
let x = ((false, true), (false, true), (false, true));
|
||||
let mut guard_count = 0;
|
||||
match x {
|
||||
((a, _), (b @ _, _), (c @ false, _))
|
||||
| ((a, _), (b @ _, _), (_, c @ true))
|
||||
| ((a, _), (_, b @ _), (c @ false, _))
|
||||
| ((a, _), (_, b @ _), (_, c @ true))
|
||||
| ((_, a), (b @ _, _), (c @ false, _))
|
||||
| ((_, a), (b @ _, _), (_, c @ true))
|
||||
| ((_, a), (_, b @ _), (c @ false, _))
|
||||
| ((_, a), (_, b @ _), (_, c @ true))
|
||||
if {
|
||||
guard_count += 1;
|
||||
(a, b, c) == target
|
||||
} =>
|
||||
{
|
||||
guard_count
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(search((false, false, false)), 1);
|
||||
assert_eq!(search((false, false, true)), 2);
|
||||
assert_eq!(search((false, true, false)), 3);
|
||||
assert_eq!(search((false, true, true)), 4);
|
||||
assert_eq!(search((true, false, false)), 5);
|
||||
assert_eq!(search((true, false, true)), 6);
|
||||
assert_eq!(search((true, true, false)), 7);
|
||||
assert_eq!(search((true, true, true)), 8);
|
||||
|
||||
assert_eq!(search_old_style((false, false, false)), 1);
|
||||
assert_eq!(search_old_style((false, false, true)), 2);
|
||||
assert_eq!(search_old_style((false, true, false)), 3);
|
||||
assert_eq!(search_old_style((false, true, true)), 4);
|
||||
assert_eq!(search_old_style((true, false, false)), 5);
|
||||
assert_eq!(search_old_style((true, false, true)), 6);
|
||||
assert_eq!(search_old_style((true, true, false)), 7);
|
||||
assert_eq!(search_old_style((true, true, true)), 8);
|
||||
}
|
Loading…
Reference in New Issue
Block a user