diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/ui/pattern/bindings-after-at | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/pattern/bindings-after-at')
43 files changed, 3474 insertions, 0 deletions
diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs new file mode 100644 index 000000000..2b349f0ed --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs @@ -0,0 +1,47 @@ +// run-pass + +// Test copy + +struct A { a: i32, b: i32 } +struct B { a: i32, b: C } +struct D { a: i32, d: C } +#[derive(Copy,Clone)] +struct C { c: i32 } + +pub fn main() { + match (A {a: 10, b: 20}) { + x@A {a, b: 20} => { assert!(x.a == 10); assert!(a == 10); } + A {b: _b, ..} => { panic!(); } + } + + let mut x@B {b, ..} = B {a: 10, b: C {c: 20}}; + assert_eq!(x.a, 10); + x.b.c = 30; + assert_eq!(b.c, 20); + let mut y@D {d, ..} = D {a: 10, d: C {c: 20}}; + assert_eq!(y.a, 10); + y.d.c = 30; + assert_eq!(d.c, 20); + + let some_b = Some(B { a: 10, b: C { c: 20 } }); + + // in irrefutable pattern + if let Some(x @ B { b, .. }) = some_b { + assert_eq!(x.b.c, 20); + assert_eq!(b.c, 20); + } else { + unreachable!(); + } + + let some_b = Some(B { a: 10, b: C { c: 20 } }); + + if let Some(x @ B { b: mut b @ C { c }, .. }) = some_b { + assert_eq!(x.b.c, 20); + assert_eq!(b.c, 20); + b.c = 30; + assert_eq!(b.c, 30); + assert_eq!(c, 20); + } else { + unreachable!(); + } +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs new file mode 100644 index 000000000..9d1f08d6e --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs @@ -0,0 +1,37 @@ +// This test is taken directly from #16053. +// It checks that you cannot use an AND-pattern (`binding @ pat`) +// where one side is by-ref and the other is by-move. + +struct X { + x: (), +} + +fn main() { + let x = Some(X { x: () }); + match x { + Some(ref _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + None => panic!(), + } + + let x = Some(X { x: () }); + match x { + Some(_z @ ref _y) => {} + //~^ ERROR borrow of moved value + None => panic!(), + } + + let mut x = Some(X { x: () }); + match x { + Some(ref mut _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + None => panic!(), + } + + let mut x = Some(X { x: () }); + match x { + Some(_z @ ref mut _y) => {} + //~^ ERROR borrow of moved value + None => panic!(), + } +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr new file mode 100644 index 000000000..c8b45fd24 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -0,0 +1,79 @@ +error: cannot move out of value because it is borrowed + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14 + | +LL | Some(ref _y @ _z) => {} + | ------^^^-- + | | | + | | value moved into `_z` here + | value borrowed, by `_y`, here + +error: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14 + | +LL | Some(_z @ ref _y) => {} + | --^^^------ + | | | + | | value borrowed here after move + | value moved into `_z` here + | move occurs because `_z` has type `X` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _z @ ref _y) => {} + | +++ + +error: cannot move out of value because it is borrowed + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14 + | +LL | Some(ref mut _y @ _z) => {} + | ----------^^^-- + | | | + | | value moved into `_z` here + | value borrowed, by `_y`, here + +error: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14 + | +LL | Some(_z @ ref mut _y) => {} + | --^^^---------- + | | | + | | value borrowed here after move + | value moved into `_z` here + | move occurs because `_z` has type `X` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _z @ ref mut _y) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14 + | +LL | Some(ref _y @ _z) => {} + | ^^^^^^ -- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `X`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _y @ ref _z) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14 + | +LL | Some(ref mut _y @ _z) => {} + | ^^^^^^^^^^ -- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `X`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref mut _y @ ref _z) => {} + | +++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs new file mode 100644 index 000000000..1816a74a0 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs @@ -0,0 +1,11 @@ +// See issue #12534. + +fn main() {} + +struct A(Box<u8>); + +fn f(a @ A(u): A) -> Box<u8> { + //~^ ERROR use of partially moved value + drop(a); + u +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr new file mode 100644 index 000000000..a481ca468 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of partially moved value + --> $DIR/bind-by-move-no-subbindings-fun-param.rs:7:6 + | +LL | fn f(a @ A(u): A) -> Box<u8> { + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `Box<u8>`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs new file mode 100644 index 000000000..a61d68215 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -0,0 +1,31 @@ +// Test that moving on both sides of an `@` pattern is not allowed. + +fn main() { + struct U; // Not copy! + + // Prevent promotion: + fn u() -> U { + U + } + + let a @ b = U; //~ ERROR use of moved value + + let a @ (b, c) = (U, U); //~ ERROR use of partially moved value + + let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value + + match Ok(U) { + a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value + //~^ ERROR use of moved value + } + + fn fun(a @ b: U) {} //~ ERROR use of moved value + + match [u(), u(), u(), u()] { + xs @ [a, .., b] => {} //~ ERROR use of partially moved value + } + + match [u(), u(), u(), u()] { + xs @ [_, ys @ .., _] => {} //~ ERROR use of partially moved value + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr new file mode 100644 index 000000000..324897151 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -0,0 +1,112 @@ +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:11:9 + | +LL | let a @ b = U; + | ^ - - move occurs because value has type `U`, which does not implement the `Copy` trait + | | | + | | value moved here + | value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:13:9 + | +LL | let a @ (b, c) = (U, U); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, ref c) = (U, U); + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:15:9 + | +LL | let a @ (b, c) = (u(), u()); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, ref c) = (u(), u()); + | +++ +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:18:16 + | +LL | match Ok(U) { + | ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait +LL | a @ Ok(b) | a @ Err(b) => {} + | - ^ value used here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Ok(b) | a @ Err(b) => {} + | +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:18:29 + | +LL | match Ok(U) { + | ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait +LL | a @ Ok(b) | a @ Err(b) => {} + | - ^ value used here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Ok(b) | ref a @ Err(b) => {} + | +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:25:9 + | +LL | xs @ [a, .., b] => {} + | ^^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref xs @ [a, .., ref b] => {} + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:29:9 + | +LL | xs @ [_, ys @ .., _] => {} + | ^^ -- value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref xs @ [_, ref ys @ .., _] => {} + | +++ +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:22:12 + | +LL | fn fun(a @ b: U) {} + | ^ - value moved here + | | + | value used here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs new file mode 100644 index 000000000..fbdefd9d3 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs @@ -0,0 +1,84 @@ +// check-pass + +// Test `@` patterns combined with `box` patterns. + +#![feature(box_patterns)] + +#[derive(Copy, Clone)] +struct C; + +fn c() -> C { C } + +struct NC; + +fn nc() -> NC { NC } + +fn main() { + let ref a @ box b = Box::new(C); // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + + let ref a @ box b = Box::new(c()); // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + + fn f3(ref a @ box b: Box<C>) { // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + } + match Box::new(c()) { + ref a @ box b => { // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + } + } + + let ref a @ box ref b = Box::new(NC); // OK. + drop(a); + drop(b); + + fn f4(ref a @ box ref b: Box<NC>) { // OK. + drop(a); + drop(b) + } + + match Box::new(nc()) { + ref a @ box ref b => { // OK. + drop(a); + drop(b); + } + } + + match Box::new([Ok(c()), Err(nc()), Ok(c())]) { + box [Ok(a), ref xs @ .., Err(ref b)] => { + let _: C = a; + let _: &[Result<C, NC>; 1] = xs; + let _: &NC = b; + } + _ => {} + } + + match [Ok(Box::new(c())), Err(Box::new(nc())), Ok(Box::new(c())), Ok(Box::new(c()))] { + [Ok(box a), ref xs @ .., Err(box ref b), Err(box ref c)] => { + let _: C = a; + let _: &[Result<Box<C>, Box<NC>>; 1] = xs; + let _: &NC = b; + let _: &NC = c; + } + _ => {} + } + + match Box::new([Ok(c()), Err(nc()), Ok(c())]) { + box [Ok(a), ref xs @ .., Err(b)] => {} + _ => {} + } + + match [Ok(Box::new(c())), Err(Box::new(nc())), Ok(Box::new(c())), Ok(Box::new(c()))] { + [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} + _ => {} + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs new file mode 100644 index 000000000..45aa65e67 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs @@ -0,0 +1,69 @@ +// Test `@` patterns combined with `box` patterns. + +#![feature(box_patterns)] + +#[derive(Copy, Clone)] +struct C; + +fn c() -> C { + C +} + +struct NC; + +fn nc() -> NC { + NC +} + +fn main() { + let a @ box &b = Box::new(&C); + + let a @ box b = Box::new(C); + + fn f1(a @ box &b: Box<&C>) {} + + fn f2(a @ box b: Box<C>) {} + + match Box::new(C) { + a @ box b => {} + } + + let ref a @ box b = Box::new(NC); //~ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + + let ref a @ box ref mut b = Box::new(nc()); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref a @ box ref mut b = Box::new(NC); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref a @ box ref mut b = Box::new(NC); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = NC; + let ref a @ box ref mut b = Box::new(NC); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = NC; + drop(a); + + let ref mut a @ box ref b = Box::new(NC); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = Box::new(NC); + drop(b); + + fn f5(ref mut a @ box ref b: Box<NC>) { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = Box::new(NC); + drop(b); + } + + match Box::new(nc()) { + ref mut a @ box ref b => { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = Box::new(NC); + drop(b); + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr new file mode 100644 index 000000000..f27df32cc --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -0,0 +1,145 @@ +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-at-and-box.rs:31:9 + | +LL | let ref a @ box b = Box::new(NC); + | -----^^^^^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:34:9 + | +LL | let ref a @ box ref mut b = Box::new(nc()); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:36:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:38:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:42:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:48:9 + | +LL | let ref mut a @ box ref b = Box::new(NC); + | ---------^^^^^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:62:9 + | +LL | ref mut a @ box ref b => { + | ---------^^^^^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:54:11 + | +LL | fn f5(ref mut a @ box ref b: Box<NC>) { + | ---------^^^^^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-at-and-box.rs:31:9 + | +LL | let ref a @ box b = Box::new(NC); + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `NC`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ box ref b = Box::new(NC); + | +++ + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:38:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = NC; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:42:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = NC; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:48:9 + | +LL | let ref mut a @ box ref b = Box::new(NC); + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:62:9 + | +LL | ref mut a @ box ref b => { + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:54:11 + | +LL | fn f5(ref mut a @ box ref b: Box<NC>) { + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs new file mode 100644 index 000000000..0108861cf --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs @@ -0,0 +1,49 @@ +// check-pass + +// Test `Copy` bindings in the rhs of `@` patterns. + +#[derive(Copy, Clone)] +struct C; + +fn mk_c() -> C { C } + +#[derive(Copy, Clone)] +struct P<A, B>(A, B); + +enum E<A, B> { L(A), R(B) } + +fn main() { + let a @ b @ c @ d = C; + let a @ (b, c) = (C, mk_c()); + let a @ P(b, P(c, d)) = P(mk_c(), P(C, C)); + let a @ [b, c] = [C, C]; + let a @ [b, .., c] = [C, mk_c(), C]; + let a @ [b, mid @ .., c] = [C, mk_c(), C]; + let a @ &(b, c) = &(C, C); + let a @ &(b, &P(c, d)) = &(mk_c(), &P(C, C)); + + fn foo(a @ [b, mid @ .., c]: [C; 3]) {} + + use self::E::*; + match L(C) { + L(a) | R(a) => { + let a: C = a; + drop(a); + drop(a); + } + } + match R(&L(&mk_c())) { + L(L(&a)) | L(R(&a)) | R(L(&a)) | R(R(&a)) => { + let a: C = a; + drop(a); + drop(a); + } + } + + match Ok(mk_c()) { + Ok(ref a @ b) | Err(b @ ref a) => { + let _: &C = a; + let _: C = b; + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs new file mode 100644 index 000000000..82f16fca6 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs @@ -0,0 +1,7 @@ +// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented even with promotion. +// Currently this logic exists in THIR match checking as opposed to borrowck. + +fn main() { + struct U; + let a @ ref b = U; //~ ERROR borrow of moved value +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr new file mode 100644 index 000000000..d6474f1b4 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -0,0 +1,17 @@ +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:6:9 + | +LL | let a @ ref b = U; + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs new file mode 100644 index 000000000..06dc6e1c4 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs @@ -0,0 +1,80 @@ +// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented. + +fn main() { + struct U; + + // Prevent promotion. + fn u() -> U { + U + } + + fn f1(a @ ref b: U) {} + //~^ ERROR borrow of moved value + + fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of partially moved value + fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + //~^ ERROR borrow of moved value + + let a @ ref b = U; + //~^ ERROR borrow of moved value + let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of partially moved value + let a @ [ref mut b, ref c] = [U, U]; + //~^ ERROR borrow of moved value + let a @ ref b = u(); + //~^ ERROR borrow of moved value + let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of partially moved value + let a @ [ref mut b, ref c] = [u(), u()]; + //~^ ERROR borrow of moved value + + match Some(U) { + a @ Some(ref b) => {} + //~^ ERROR borrow of moved value + None => {} + } + match Some((U, U)) { + a @ Some((mut b @ ref mut c, d @ ref e)) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + None => {} + } + match Some([U, U]) { + mut a @ Some([ref b, ref mut c]) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some(u()) { + a @ Some(ref b) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some((u(), u())) { + a @ Some((mut b @ ref mut c, d @ ref e)) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + None => {} + } + match Some([u(), u()]) { + mut a @ Some([ref b, ref mut c]) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr new file mode 100644 index 000000000..389e86e64 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -0,0 +1,487 @@ +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:22:9 + | +LL | let a @ ref b = U; + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -^^^^^^^^^^^^---------^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (ref mut b @ ref mut c, d @ ref e) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (mut b @ ref mut c, ref d @ ref e) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9 + | +LL | let a @ [ref mut b, ref c] = [U, U]; + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ [ref mut b, ref c] = [U, U]; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9 + | +LL | let a @ ref b = u(); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = u(); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -^^^^^^^^^^^^---------^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (ref mut b @ ref mut c, d @ ref e) = (u(), u()); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9 + | +LL | let a @ [ref mut b, ref c] = [u(), u()]; + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ [ref mut b, ref c] = [u(), u()]; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9 + | +LL | a @ Some(ref b) => {} + | -^^^^^^^^-----^ + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9 + | +LL | mut a @ Some([ref b, ref mut c]) => {} + | -----^^^^^^^^^-----^^---------^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([ref b, ref mut c]) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 + | +LL | a @ Some(ref b) => {} + | -^^^^^^^^-----^ + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 + | +LL | mut a @ Some([ref b, ref mut c]) => {} + | -----^^^^^^^^^-----^^---------^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([ref b, ref mut c]) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 + | +LL | fn f1(a @ ref b: U) {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f1(ref a @ ref b: U) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -----^^^^^^^^-----^^^^^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(ref mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(mut a @ (ref b @ ref c, mut d @ ref e): (U, U)) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -----^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(mut a @ (b @ ref c, ref mut d @ ref e): (U, U)) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11 + | +LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {} + | +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (U, U); + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); + | +++ +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 + | +LL | match Some((U, U)) { + | ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | - value moved here ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30 + | +LL | match Some([U, U]) { + | ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait +LL | mut a @ Some([ref b, ref mut c]) => {} + | ----- ^^^^^^^^^ value borrowed here after move + | | + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18 + | +LL | match Some(u()) { + | --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait +LL | a @ Some(ref b) => {} + | - ^^^^^ value borrowed here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + | +LL | match Some((u(), u())) { + | ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | - value moved here ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30 + | +LL | match Some([u(), u()]) { + | ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait +LL | mut a @ Some([ref b, ref mut c]) => {} + | ----- ^^^^^^^^^ value borrowed here after move + | | + | value moved here + +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | ^^^^^ ----- value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 33 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs new file mode 100644 index 000000000..0b0a78010 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs @@ -0,0 +1,82 @@ +// Test that `ref mut? @ pat_with_by_move_bindings` is prevented. + +fn main() { + struct U; + + // Prevent promotion. + fn u() -> U { + U + } + + fn f1(ref a @ b: U) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value + + let ref a @ b = U; + //~^ ERROR cannot move out of value because it is borrowed + let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + let ref mut a @ [b, mut c] = [U, U]; + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value + let ref a @ b = u(); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + let ref mut a @ [b, mut c] = [u(), u()]; + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value + + match Some(U) { + ref a @ Some(b) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some((U, U)) { + ref a @ Some((ref b @ mut c, ref d @ e)) => {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + None => {} + } + match Some([U, U]) { + ref mut a @ Some([b, mut c]) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some(u()) { + ref a @ Some(b) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some((u(), u())) { + ref a @ Some((ref b @ mut c, ref d @ e)) => {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some([u(), u()]) { + ref mut a @ Some([b, mut c]) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr new file mode 100644 index 000000000..770bb8953 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -0,0 +1,375 @@ +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:24:9 + | +LL | let ref a @ b = U; + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:26:9 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:26:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:26:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9 + | +LL | let ref mut a @ [b, mut c] = [U, U]; + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 + | +LL | let ref a @ b = u(); + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:9 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9 + | +LL | let ref mut a @ [b, mut c] = [u(), u()]; + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:47:9 + | +LL | ref a @ Some(b) => {} + | -----^^^^^^^^-^ + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:52:9 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:52:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:52:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ---------^^^^^^^^^-^^-----^^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9 + | +LL | ref a @ Some(b) => {} + | -----^^^^^^^^-^ + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ---------^^^^^^^^^-^^-----^^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 + | +LL | fn f1(ref a @ b: U) {} + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11 + | +LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9 + | +LL | let ref mut a @ [b, mut c] = [U, U]; + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ [b, ref mut c] = [U, U]; + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 + | +LL | let ref a @ b = u(); + | ^^^^^ - --- move occurs because value has type `U`, which does not implement the `Copy` trait + | | | + | | value moved here + | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = u(); + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | ^^^^^ ----- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref b @ ref mut c, ref d @ e) = (u(), u()); + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref b @ mut c, ref d @ ref e) = (u(), u()); + | +++ + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9 + | +LL | let ref mut a @ [b, mut c] = [u(), u()]; + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ [b, ref mut c] = [u(), u()]; + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | ^^^^^ ----- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((ref b @ ref mut c, ref d @ e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((ref b @ mut c, ref d @ ref e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 + | +LL | fn f1(ref a @ b: U) {} + | ^^^^^ - value moved here + | | + | value borrowed here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | ^^^^^ ----- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11 + | +LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 36 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs new file mode 100644 index 000000000..df213f688 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs @@ -0,0 +1,45 @@ +// check-pass + +// Test that `ref` patterns may be used on both sides +// of an `@` pattern according to NLL borrowck. + +fn main() { + struct U; // Not copy! + + // Promotion: + let ref a @ ref b = U; + let _: &U = a; + let _: &U = b; + + // Prevent promotion: + fn u() -> U { U } + + let ref a @ ref b = u(); + let _: &U = a; + let _: &U = b; + + let ref a @ (ref b, [ref c, ref d]) = (u(), [u(), u()]); + let _: &(U, [U; 2]) = a; + let _: &U = b; + let _: &U = c; + let _: &U = d; + + fn f1(ref a @ (ref b, [ref c, ref mid @ .., ref d]): (U, [U; 4])) {} + + let a @ (b, [c, d]) = &(u(), [u(), u()]); + let _: &(U, [U; 2]) = a; + let _: &U = b; + let _: &U = c; + let _: &U = d; + + let ref a @ &ref b = &u(); + let _: &&U = a; + let _: &U = b; + + match Ok(u()) { + ref a @ Ok(ref b) | ref a @ Err(ref b) => { + let _: &Result<U, U> = a; + let _: &U = b; + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs new file mode 100644 index 000000000..6bc0d346c --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -0,0 +1,136 @@ +enum Option<T> { + None, + Some(T), +} + +fn main() { + match &mut Some(1) { + ref mut z @ &mut Some(ref a) => { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + **z = None; + println!("{}", *a); + } + _ => () + } + + struct U; + + // Prevent promotion: + fn u() -> U { U } + + fn f1(ref a @ ref mut b: U) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + fn f2(ref mut a @ ref b: U) {} + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + fn f4_also_moved(ref a @ ref mut b @ c: U) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + + let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + + let ref a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref mut a @ ref b = U; + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref mut a @ (ref b, ref c) = (U, U); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + + let ref mut a @ ref b = u(); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = u(); + drop(b); + let ref a @ ref mut b = u(); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = u(); + drop(a); + + let ref mut a @ ref b = U; + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + *a = U; + drop(b); + let ref a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + *b = U; + drop(a); + + match Ok(U) { + ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *a = Err(U); + drop(b); + } + } + + match Ok(U) { + ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *b = U; + drop(a); + } + } + + match Ok(U) { + ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard + _ => {} + } + match Ok(U) { + ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot assign to `*a`, as it is immutable for the pattern guard + _ => {} + } + match Ok(U) { + ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot move out of `b` in pattern guard + //~| ERROR cannot move out of `b` in pattern guard + _ => {} + } + match Ok(U) { + ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot move out of `a` in pattern guard + //~| ERROR cannot move out of `a` in pattern guard + _ => {} + } + + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = U; + *c = U; + + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = U; + drop(a); + + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = U; //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *c = U; + drop(a); + let ref mut a @ (ref b, ref c) = (U, U); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr new file mode 100644 index 000000000..8546b4bb4 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -0,0 +1,445 @@ +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9 + | +LL | ref mut z @ &mut Some(ref a) => { + | ---------^^^^^^^^^^^^^-----^ + | | | + | | immutable borrow, by `a`, occurs here + | mutable borrow, by `z`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:9 + | +LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub + | ---------^^^^-----------------^ + | | | | + | | | another mutable borrow, by `c`, occurs here + | | also borrowed as immutable, by `b`, here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:22 + | +LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub + | -----^^^--------- + | | | + | | mutable borrow, by `c`, occurs here + | immutable borrow, by `b`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9 + | +LL | let ref a @ ref mut b = U; + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9 + | +LL | let ref mut a @ ref b = U; + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9 + | +LL | let ref mut a @ (ref b, ref c) = (U, U); + | ---------^^^^-----^^-----^ + | | | | + | | | immutable borrow, by `c`, occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 + | +LL | let ref mut a @ ref b = u(); + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9 + | +LL | let ref a @ ref mut b = u(); + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:57:9 + | +LL | let ref mut a @ ref b = U; + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:61:9 + | +LL | let ref a @ ref mut b = U; + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:9 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { + | ---------^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:33 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { + | ---------^^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | -----^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | -----^^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | -----^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | -----^^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + | ---------^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + | ---------^^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | -----^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | -----^^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ---------^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ---------^^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9 + | +LL | let ref mut a @ (ref b, ref c) = (U, U); + | ---------^^^^-----^^-----^ + | | | | + | | | immutable borrow, by `c`, occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11 + | +LL | fn f1(ref a @ ref mut b: U) {} + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11 + | +LL | fn f2(ref mut a @ ref b: U) {} + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11 + | +LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} + | -----^^^^^^^^^^^----------------^^^^^^^^ + | | | + | | mutable borrow, by `mid`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | -----^^^------------- + | | | | + | | | also moved into `c` here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | ---------^^^- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31 + | +LL | ref mut z @ &mut Some(ref a) => { + | --------- ^^^^^ immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | **z = None; + | ---------- mutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 + | +LL | let ref mut a @ ref b = u(); + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9 + | +LL | let ref a @ ref mut b = u(); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = u(); + | -------- mutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | ----- ^^^^^^^^^ mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | drop(a); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | ----- ^^^^^^^^^ mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | drop(a); + | - immutable borrow later used here + +error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^^ cannot assign + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + | ^^^^^^^^^^^ cannot assign + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error[E0507]: cannot move out of `b` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `b` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `a` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `a` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +LL | +LL | *b = U; + | ------ mutable borrow later used here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | ----- ^^^^^^^^^ - value moved here + | | | + | | value borrowed here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 47 previous errors + +Some errors have detailed explanations: E0382, E0502, E0507, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs new file mode 100644 index 000000000..99739c7bc --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -0,0 +1,109 @@ +// Test that `ref mut x @ ref mut y` and varieties of that are not allowed. + +fn main() { + struct U; + + fn u() -> U { U } + + fn f1(ref mut a @ ref mut b: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + fn f2(ref mut a @ ref mut b: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + fn f3( + ref mut a @ [ + //~^ ERROR cannot borrow value as mutable more than once at a time + [ref b @ .., _], + [_, ref mut mid @ ..], + .., + [..], + ] : [[U; 4]; 5] + ) {} + fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + drop(a); + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + drop(b); + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + *a = U; + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + *b = U; + + let ref mut a @ ( + //~^ ERROR cannot borrow value as mutable more than once at a time + ref mut b, + [ + ref mut c, + ref mut d, + ref e, + ] + ) = (U, [U, U, U]); + + let ref mut a @ ( + //~^ ERROR cannot borrow value as mutable more than once at a time + ref mut b, + [ + ref mut c, + ref mut d, + ref e, + ] + ) = (u(), [u(), u(), u()]); + + let a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR borrow of moved value + let mut val = (U, [U, U]); + let a @ (b, [c, d]) = &mut val; // Same as ^-- + //~^ ERROR borrow of moved value + + let a @ &mut ref mut b = &mut U; + //~^ ERROR borrow of moved value + let a @ &mut (ref mut b, ref mut c) = &mut (U, U); + //~^ ERROR borrow of moved value + + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + } + } + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + *b = U; + } + } + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + *a = Err(U); + + // FIXME: The binding name value used above makes for problematic diagnostics. + // Resolve that somehow... + } + } + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + drop(a); + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr new file mode 100644 index 000000000..ad4ce7952 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -0,0 +1,359 @@ +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:26:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:33:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:36:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:44:9 + | +LL | let ref mut a @ ( + | ^-------- + | | + | _________first mutable borrow, by `a`, occurs here + | | +LL | | +LL | | ref mut b, + | | --------- another mutable borrow, by `b`, occurs here +LL | | [ +LL | | ref mut c, + | | --------- another mutable borrow, by `c`, occurs here +LL | | ref mut d, + | | --------- another mutable borrow, by `d`, occurs here +LL | | ref e, + | | ----- also borrowed as immutable, by `e`, here +LL | | ] +LL | | ) = (U, [U, U, U]); + | |_____^ + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:54:9 + | +LL | let ref mut a @ ( + | ^-------- + | | + | _________first mutable borrow, by `a`, occurs here + | | +LL | | +LL | | ref mut b, + | | --------- another mutable borrow, by `b`, occurs here +LL | | [ +LL | | ref mut c, + | | --------- another mutable borrow, by `c`, occurs here +LL | | ref mut d, + | | --------- another mutable borrow, by `d`, occurs here +LL | | ref e, + | | ----- also borrowed as immutable, by `e`, here +LL | | ] +LL | | ) = (u(), [u(), u(), u()]); + | |_________^ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:64:9 + | +LL | let a @ (ref mut b, ref mut c) = (U, U); + | -^^^^---------^^---------^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9 + | +LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- + | -^^^^-^^^-^^-^^ + | | | | | + | | | | value borrowed here after move + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, [c, d]) = &mut val; // Same as ^-- + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 + | +LL | let a @ &mut ref mut b = &mut U; + | -^^^^^^^^--------- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ &mut ref mut b = &mut U; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9 + | +LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); + | -^^^^^^^^^---------^^---------^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ &mut (ref mut b, ref mut c) = &mut (U, U); + | +++ + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:76:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11 + | +LL | fn f1(ref mut a @ ref mut b: U) {} + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11 + | +LL | fn f2(ref mut a @ ref mut b: U) {} + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9 + | +LL | ref mut a @ [ + | ^-------- + | | + | _________first mutable borrow, by `a`, occurs here + | | +LL | | +LL | | [ref b @ .., _], + | | ---------- also borrowed as immutable, by `b`, here +LL | | [_, ref mut mid @ ..], + | | ---------------- another mutable borrow, by `mid`, occurs here +LL | | .., +LL | | [..], +LL | | ] : [[U; 4]; 5] + | |_________^ + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | ---------^^^------------- + | | | | + | | | also moved into `c` here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | ---------^^^- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9 + | +LL | let ref mut a @ ref mut b = U; + | ^^^^^^^^^ --------- first mutable borrow occurs here + | | + | second mutable borrow occurs here +... +LL | drop(b); + | - first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9 + | +LL | let ref mut a @ ref mut b = U; + | ^^^^^^^^^ --------- first mutable borrow occurs here + | | + | second mutable borrow occurs here +... +LL | *b = U; + | ------ first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | *a = Err(U); + | ----------- first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | *a = Err(U); + | ----------- first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | drop(a); + | - first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | drop(a); + | - first borrow later used here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | --------- ^^^^^^^^^ - value moved here + | | | + | | value borrowed here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 31 previous errors + +Some errors have detailed explanations: E0382, E0499. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/box-patterns.rs b/tests/ui/pattern/bindings-after-at/box-patterns.rs new file mode 100644 index 000000000..9db37253c --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/box-patterns.rs @@ -0,0 +1,35 @@ +// Test bindings-after-at with box-patterns + +// run-pass + +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(x: Option<Box<i32>>) -> MatchArm { + match x { + ref bar @ Some(box n) if n > 0 => { + // bar is a &Option<Box<i32>> + assert_eq!(bar, &x); + + MatchArm::Arm(0) + }, + Some(ref bar @ box n) if n < 0 => { + // bar is a &Box<i32> here + assert_eq!(**bar, n); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(2))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(-1))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(0))), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs new file mode 100644 index 000000000..1e2c2968c --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs @@ -0,0 +1,14 @@ +// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden. + +#[derive(Copy, Clone)] +struct C; + +struct NC<A, B>(A, B); + +fn main() { + // this compiles + let a @ NC(b, c) = NC(C, C); + + let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); + //~^ ERROR use of partially moved value +} diff --git a/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr new file mode 100644 index 000000000..e0e623fa5 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of partially moved value + --> $DIR/copy-and-move-mixed.rs:12:9 + | +LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ NC(b, ref c @ NC(d, e)) = NC(C, NC(C, C)); + | +++ +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs new file mode 100644 index 000000000..dfd4d0285 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs @@ -0,0 +1,48 @@ +// Ensures the independence of each side in `binding @ subpat` +// determine their binding modes independently of each other. +// +// That is, `binding` does not influence `subpat`. +// This is important because we might want to allow `p1 @ p2`, +// where both `p1` and `p2` are syntactically unrestricted patterns. +// If `binding` is allowed to influence `subpat`, +// this would create problems for the generalization aforementioned. + + +fn main() { + struct NotCopy; + + fn f1(a @ b: &NotCopy) { // OK + let _: &NotCopy = a; + } + fn f2(ref a @ b: &NotCopy) { + let _: &&NotCopy = a; // Ok + } + + let a @ b = &NotCopy; // OK + let _: &NotCopy = a; + let ref a @ b = &NotCopy; // OK + let _: &&NotCopy = a; + + let ref a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; + let ref mut a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed + //~^ ERROR borrow of moved value + let _a: &NotCopy = a; + let _b: NotCopy = b; + match Ok(NotCopy) { + Ok(ref a @ b) | Err(b @ ref a) => { + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + let _a: &NotCopy = a; + let _b: NotCopy = b; + } + } + match NotCopy { + ref a @ b => { + //~^ ERROR cannot move out of value because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr new file mode 100644 index 000000000..638bdd6db --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -0,0 +1,68 @@ +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:26:9 + | +LL | let ref a @ b = NotCopy; + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:29:9 + | +LL | let ref mut a @ b = NotCopy; + | ---------^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:34:12 + | +LL | Ok(ref a @ b) | Err(b @ ref a) => { + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: borrow of moved value + --> $DIR/default-binding-modes-both-sides-independent.rs:34:29 + | +LL | Ok(ref a @ b) | Err(b @ ref a) => { + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Ok(ref a @ b) | Err(ref b @ ref a) => { + | +++ + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:42:9 + | +LL | ref a @ b => { + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error[E0382]: borrow of moved value + --> $DIR/default-binding-modes-both-sides-independent.rs:29:9 + | +LL | let ref mut a @ b = NotCopy; + | ^^^^^^^^^ - ------- move occurs because value has type `NotCopy`, which does not implement the `Copy` trait + | | | + | | value moved here + | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ ref b = NotCopy; + | +++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs b/tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs new file mode 100644 index 000000000..fe7d1eba1 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs @@ -0,0 +1,12 @@ +// check-pass + +#![deny(unused_mut)] + +fn main() { + let mut is_mut @ not_mut = 42; + &mut is_mut; + ¬_mut; + let not_mut @ mut is_mut = 42; + &mut is_mut; + ¬_mut; +} diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs new file mode 100644 index 000000000..e7d99534d --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs @@ -0,0 +1,11 @@ +fn main() { + let mut is_mut @ not_mut = 42; + &mut is_mut; + &mut not_mut; + //~^ ERROR cannot borrow + + let not_mut @ mut is_mut = 42; + &mut is_mut; + &mut not_mut; + //~^ ERROR cannot borrow +} diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr new file mode 100644 index 000000000..54118dc36 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable + --> $DIR/nested-binding-modes-mut.rs:4:5 + | +LL | &mut not_mut; + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut is_mut @ mut not_mut = 42; + | +++ + +error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable + --> $DIR/nested-binding-modes-mut.rs:9:5 + | +LL | &mut not_mut; + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut not_mut @ mut is_mut = 42; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs new file mode 100644 index 000000000..adfb0387f --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs @@ -0,0 +1,11 @@ +fn main() { + let ref is_ref @ is_val = 42; + *is_ref; + *is_val; + //~^ ERROR cannot be dereferenced + + let is_val @ ref is_ref = 42; + *is_ref; + *is_val; + //~^ ERROR cannot be dereferenced +} diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr new file mode 100644 index 000000000..b378fe356 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr @@ -0,0 +1,15 @@ +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/nested-binding-modes-ref.rs:4:5 + | +LL | *is_val; + | ^^^^^^^ + +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/nested-binding-modes-ref.rs:9:5 + | +LL | *is_val; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/pattern/bindings-after-at/nested-patterns.rs b/tests/ui/pattern/bindings-after-at/nested-patterns.rs new file mode 100644 index 000000000..f06563d56 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-patterns.rs @@ -0,0 +1,14 @@ +// run-pass + + +struct A { a: u8, b: u8 } + +pub fn main() { + match (A { a: 10, b: 20 }) { + ref x @ A { ref a, b: 20 } => { + assert_eq!(x.a, 10); + assert_eq!(*a, 10); + } + A { b: ref _b, .. } => panic!(), + } +} diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs new file mode 100644 index 000000000..a709e34b5 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs @@ -0,0 +1,33 @@ +// Here we check that type ascription is syntactically invalid when +// not in the top position of an ascribing `let` binding or function parameter. + + +// This has no effect. +// We include it to demonstrate that this is the case: +#![feature(type_ascription)] + +fn main() {} + +fn _ok() { + let _a @ _b: u8 = 0; // OK. + fn _f(_a @ _b: u8) {} // OK. +} + +#[cfg(FALSE)] +fn case_1() { + let a: u8 @ b = 0; + //~^ ERROR expected one of `!` +} + +#[cfg(FALSE)] +fn case_2() { + let a @ (b: u8); + //~^ ERROR expected one of `!` + //~| ERROR expected one of `)` +} + +#[cfg(FALSE)] +fn case_3() { + let a: T1 @ Outer(b: T2); + //~^ ERROR expected one of `!` +} diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr new file mode 100644 index 000000000..27660ae40 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr @@ -0,0 +1,26 @@ +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:18:15 + | +LL | let a: u8 @ b = 0; + | ^ expected one of 7 possible tokens + +error: expected one of `)`, `,`, `@`, or `|`, found `:` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:15 + | +LL | let a @ (b: u8); + | ^ expected one of `)`, `,`, `@`, or `|` + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `)` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:19 + | +LL | let a @ (b: u8); + | ^ expected one of 7 possible tokens + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:31:15 + | +LL | let a: T1 @ Outer(b: T2); + | ^ expected one of 7 possible tokens + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs b/tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs new file mode 100644 index 000000000..383e377a5 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs @@ -0,0 +1,43 @@ +// Test bindings-after-at with or-patterns and box-patterns + +// run-pass + +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option<Box<Test>>) -> MatchArm { + match foo { + ref bar @ Some(box Test::Foo | box Test::Bar) => { + assert_eq!(bar, &foo); + + MatchArm::Arm(0) + }, + Some(ref bar @ box Test::Baz | ref bar @ box Test::Qux) => { + assert!(**bar == Test::Baz || **bar == Test::Qux); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs new file mode 100644 index 000000000..d315f7ee3 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -0,0 +1,54 @@ +// Test bindings-after-at with or-patterns and slice-patterns + +// run-pass + + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option<Test>]) -> MatchArm { + match foo { + bar @ [Some(Test::Foo), .., Some(Test::Qux | Test::Foo)] => { + assert_eq!(bar, foo); + + MatchArm::Arm(0) + }, + [.., bar @ Some(Test::Bar | Test::Qux), _] => { + assert!(bar == &Some(Test::Bar) || bar == &Some(Test::Qux)); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + // path 1a + assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Qux), Some(Test::Baz)]), MatchArm::Arm(1)); + // path 3 + assert_eq!(test(&foo[1..2]), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/or-patterns.rs b/tests/ui/pattern/bindings-after-at/or-patterns.rs new file mode 100644 index 000000000..fcc361489 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/or-patterns.rs @@ -0,0 +1,38 @@ +// Test bindings-after-at with or-patterns + +// run-pass + + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option<Test>) -> MatchArm { + match foo { + bar @ Some(Test::Foo | Test::Bar) => { + assert!(bar == Some(Test::Foo) || bar == Some(Test::Bar)); + + MatchArm::Arm(0) + }, + Some(_) => MatchArm::Arm(1), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Test::Foo)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Bar)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Baz)), MatchArm::Arm(1)); + assert_eq!(test(Some(Test::Qux)), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs new file mode 100644 index 000000000..f167a3952 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs @@ -0,0 +1,29 @@ +// Test that `binding @ subpat` acts as a product context with respect to duplicate binding names. +// The code that is tested here lives in resolve (see `resolve_pattern_inner`). + + +fn main() { + fn f(a @ a @ a: ()) {} + //~^ ERROR identifier `a` is bound more than once in this parameter list + //~| ERROR identifier `a` is bound more than once in this parameter list + + match Ok(0) { + Ok(a @ b @ a) + //~^ ERROR identifier `a` is bound more than once in the same pattern + | Err(a @ b @ a) + //~^ ERROR identifier `a` is bound more than once in the same pattern + => {} + } + + let a @ a @ a = (); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + let ref a @ ref a = (); + //~^ ERROR identifier `a` is bound more than once in the same pattern + let ref mut a @ ref mut a = (); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let a @ (Ok(a) | Err(a)) = Ok(()); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern +} diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr new file mode 100644 index 000000000..a165549f6 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -0,0 +1,64 @@ +error[E0415]: identifier `a` is bound more than once in this parameter list + --> $DIR/pat-at-same-name-both.rs:6:14 + | +LL | fn f(a @ a @ a: ()) {} + | ^ used as parameter more than once + +error[E0415]: identifier `a` is bound more than once in this parameter list + --> $DIR/pat-at-same-name-both.rs:6:18 + | +LL | fn f(a @ a @ a: ()) {} + | ^ used as parameter more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:11:20 + | +LL | Ok(a @ b @ a) + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:13:23 + | +LL | | Err(a @ b @ a) + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:18:13 + | +LL | let a @ a @ a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:18:17 + | +LL | let a @ a @ a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:21:21 + | +LL | let ref a @ ref a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:23:29 + | +LL | let ref mut a @ ref mut a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:26:17 + | +LL | let a @ (Ok(a) | Err(a)) = Ok(()); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:26:26 + | +LL | let a @ (Ok(a) | Err(a)) = Ok(()); + | ^ used in a pattern more than once + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0415, E0416. +For more information about an error, try `rustc --explain E0415`. diff --git a/tests/ui/pattern/bindings-after-at/slice-patterns.rs b/tests/ui/pattern/bindings-after-at/slice-patterns.rs new file mode 100644 index 000000000..4f4c96e45 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/slice-patterns.rs @@ -0,0 +1,39 @@ +// Test bindings-after-at with slice-patterns + +// run-pass + + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(foo: &[i32]) -> MatchArm { + match foo { + [bar @ .., n] if n == &5 => { + for i in bar { + assert!(i < &5); + } + + MatchArm::Arm(0) + }, + bar @ [x0, .., xn] => { + assert_eq!(x0, &1); + assert_eq!(x0, &1); + assert_eq!(xn, &4); + assert_eq!(bar, &[1, 2, 3, 4]); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![1, 2, 3, 4, 5]; + + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..4]), MatchArm::Arm(1)); + assert_eq!(test(&foo[0..1]), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs new file mode 100644 index 000000000..50ac0ef27 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs @@ -0,0 +1,16 @@ +// Here we check that `_ @ sub` is syntactically invalid +// and comes with a nice actionable suggestion. + +fn main() {} + +#[cfg(FALSE)] +fn wild_before_at_is_bad_syntax() { + let _ @ a = 0; + //~^ ERROR pattern on wrong side of `@` + let _ @ ref a = 0; + //~^ ERROR pattern on wrong side of `@` + let _ @ ref mut a = 0; + //~^ ERROR pattern on wrong side of `@` + let _ @ (a, .., b) = (0, 1, 2, 3); + //~^ ERROR left-hand side of `@` must be a binding +} diff --git a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr new file mode 100644 index 000000000..2f4541584 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr @@ -0,0 +1,43 @@ +error: pattern on wrong side of `@` + --> $DIR/wild-before-at-syntactically-rejected.rs:8:9 + | +LL | let _ @ a = 0; + | -^^^- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `a @ _` + +error: pattern on wrong side of `@` + --> $DIR/wild-before-at-syntactically-rejected.rs:10:9 + | +LL | let _ @ ref a = 0; + | -^^^----- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `ref a @ _` + +error: pattern on wrong side of `@` + --> $DIR/wild-before-at-syntactically-rejected.rs:12:9 + | +LL | let _ @ ref mut a = 0; + | -^^^--------- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `ref mut a @ _` + +error: left-hand side of `@` must be a binding + --> $DIR/wild-before-at-syntactically-rejected.rs:14:9 + | +LL | let _ @ (a, .., b) = (0, 1, 2, 3); + | -^^^---------- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: aborting due to 4 previous errors + |