diff options
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/mir-opt/exponential-or.rs | 76 | ||||
| -rw-r--r-- | src/test/ui/borrowck/or-patterns.rs | 64 | ||||
| -rw-r--r-- | src/test/ui/borrowck/or-patterns.stderr | 141 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/bindings-runpass-1.rs | 25 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/bindings-runpass-2.rs | 32 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/for-loop.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/if-let-while-let.rs | 22 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/issue-67514-irrefutable-param.rs | 11 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/let-pattern.rs | 19 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/search-via-bindings.rs | 66 |
10 files changed, 474 insertions, 0 deletions
diff --git a/src/test/mir-opt/exponential-or.rs b/src/test/mir-opt/exponential-or.rs new file mode 100644 index 00000000000..4c23582e1f8 --- /dev/null +++ b/src/test/mir-opt/exponential-or.rs @@ -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 diff --git a/src/test/ui/borrowck/or-patterns.rs b/src/test/ui/borrowck/or-patterns.rs new file mode 100644 index 00000000000..5b31e2d76a0 --- /dev/null +++ b/src/test/ui/borrowck/or-patterns.rs @@ -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() {} diff --git a/src/test/ui/borrowck/or-patterns.stderr b/src/test/ui/borrowck/or-patterns.stderr new file mode 100644 index 00000000000..d3f3544426a --- /dev/null +++ b/src/test/ui/borrowck/or-patterns.stderr @@ -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`. diff --git a/src/test/ui/or-patterns/bindings-runpass-1.rs b/src/test/ui/or-patterns/bindings-runpass-1.rs new file mode 100644 index 00000000000..0087167af7e --- /dev/null +++ b/src/test/ui/or-patterns/bindings-runpass-1.rs @@ -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); +} diff --git a/src/test/ui/or-patterns/bindings-runpass-2.rs b/src/test/ui/or-patterns/bindings-runpass-2.rs new file mode 100644 index 00000000000..0e1eb7b2e03 --- /dev/null +++ b/src/test/ui/or-patterns/bindings-runpass-2.rs @@ -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); +} diff --git a/src/test/ui/or-patterns/for-loop.rs b/src/test/ui/or-patterns/for-loop.rs new file mode 100644 index 00000000000..b79af6c402e --- /dev/null +++ b/src/test/ui/or-patterns/for-loop.rs @@ -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]); +} diff --git a/src/test/ui/or-patterns/if-let-while-let.rs b/src/test/ui/or-patterns/if-let-while-let.rs new file mode 100644 index 00000000000..9256360b29d --- /dev/null +++ b/src/test/ui/or-patterns/if-let-while-let.rs @@ -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!(); + } +} diff --git a/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs b/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs new file mode 100644 index 00000000000..0c2ae44e546 --- /dev/null +++ b/src/test/ui/or-patterns/issue-67514-irrefutable-param.rs @@ -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); +} diff --git a/src/test/ui/or-patterns/let-pattern.rs b/src/test/ui/or-patterns/let-pattern.rs new file mode 100644 index 00000000000..07e37412ce8 --- /dev/null +++ b/src/test/ui/or-patterns/let-pattern.rs @@ -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); +} diff --git a/src/test/ui/or-patterns/search-via-bindings.rs b/src/test/ui/or-patterns/search-via-bindings.rs new file mode 100644 index 00000000000..eb127b881cd --- /dev/null +++ b/src/test/ui/or-patterns/search-via-bindings.rs @@ -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); +} |
