Skip to content

Commit

Permalink
reverse binding order in matches ...
Browse files Browse the repository at this point in the history
... to allow the subbinding of copyable fields in bindings after `@`

Fixes #69971
  • Loading branch information
vn-ki committed Nov 1, 2020
1 parent 0d33ab7 commit c93d25b
Show file tree
Hide file tree
Showing 21 changed files with 641 additions and 709 deletions.
15 changes: 14 additions & 1 deletion compiler/rustc_mir_build/src/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}

PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
candidate.bindings.push(Binding {
// issue #69971: the binding order should be right to left if there are more
// bindings after `@` to please the borrow checker
// Ex
// struct NonCopyStruct {
// copy_field: u32,
// }
//
// fn foo1(x: NonCopyStruct) {
// let y @ NonCopyStruct { copy_field: z } = x;
// // the above should turn into
// let z = x.copy_field;
// let y = x;
// }
candidate.bindings.insert(0, Binding {
name,
mutability,
span: match_pair.pattern.span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@ 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
//~| 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
//~| ERROR borrow of moved value
None => panic!(),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | Some(ref _y @ _z) => {}
| value borrowed, by `_y`, here

error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:14
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14
|
LL | Some(_z @ ref _y) => {}
| --^^^------
Expand All @@ -27,7 +27,7 @@ LL | Some(ref mut _y @ _z) => {}
| value borrowed, by `_y`, here

error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:14
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14
|
LL | Some(_z @ ref mut _y) => {}
| --^^^----------
Expand All @@ -37,34 +37,34 @@ LL | Some(_z @ ref mut _y) => {}
| move occurs because `_z` has type `X` which does not implement the `Copy` trait

error[E0382]: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:19
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
|
LL | Some(_z @ ref _y) => {}
| -----^^^^^^
| | |
| | value borrowed here after move
| value moved here
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 field in the pattern to avoid moving `x.0`
|
LL | Some(ref _z @ ref _y) => {}
| ^^^
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:34:19
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
|
LL | Some(_z @ ref mut _y) => {}
| -----^^^^^^^^^^
| | |
| | value borrowed here after move
| value moved here
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 field in the pattern to avoid moving `x.0`
|
LL | Some(ref _z @ ref mut _y) => {}
| ^^^
LL | Some(ref mut _y @ ref _z) => {}
| ^^^

error: aborting due to 6 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn main() {}
struct A(Box<u8>);

fn f(a @ A(u): A) -> Box<u8> {
//~^ ERROR use of moved value
//~^ ERROR use of partially moved value
drop(a);
u
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
error[E0382]: use of moved value
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:12
error[E0382]: use of partially moved value
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:6
|
LL | fn f(a @ A(u): A) -> Box<u8> {
| ------^-
| ^^^^^^-^
| | |
| | value used here after move
| value moved here
| move occurs because value has type `A`, which does not implement the `Copy` trait
| | 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

Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ fn main() {

let a @ b = U; //~ ERROR use of moved value

let a @ (b, c) = (U, 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 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
a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of partially moved value
//~^ ERROR use of partially moved value
}

fn fun(a @ b: U) {} //~ ERROR use of moved value

match [u(), u(), u(), u()] {
xs @ [a, .., b] => {} //~ ERROR use of moved value
xs @ [a, .., b] => {} //~ ERROR use of partially moved value
}

match [u(), u(), u(), u()] {
xs @ [_, ys @ .., _] => {} //~ ERROR use of moved value
xs @ [_, ys @ .., _] => {} //~ ERROR use of partially moved value
}
}
110 changes: 61 additions & 49 deletions src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
Original file line number Diff line number Diff line change
@@ -1,82 +1,94 @@
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:13:13
--> $DIR/borrowck-move-and-move.rs:13:9
|
LL | let a @ b = U;
| ----^ - move occurs because value has type `U`, which does not implement the `Copy` trait
| ^^^^- - move occurs because value has type `U`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
| | value moved here
| value used here after move

error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:15:17
error[E0382]: use of partially moved value
--> $DIR/borrowck-move-and-move.rs:15:9
|
LL | let a @ (b, c) = (U, U);
| --------^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
| ^^^^^-^^^^
| | |
| | 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[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:17:17
error[E0382]: use of partially moved value
--> $DIR/borrowck-move-and-move.rs:17:9
|
LL | let a @ (b, c) = (u(), u());
| --------^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
| ^^^^^-^^^^
| | |
| | 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[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:20:16
error[E0382]: use of partially moved value
--> $DIR/borrowck-move-and-move.rs:20:9
|
LL | match Ok(U) {
| ----- move occurs because value has type `std::result::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
| | 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 field in the pattern to avoid moving the value
|
LL | a @ Ok(ref b) | a @ Err(b) => {}
| ^^^

error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:20:29
error[E0382]: use of partially moved value
--> $DIR/borrowck-move-and-move.rs:20:21
|
LL | match Ok(U) {
| ----- move occurs because value has type `std::result::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
| | 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 field in the pattern to avoid moving the value
|
LL | a @ Ok(b) | a @ Err(ref b) => {}
| ^^^

error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:27:22
error[E0382]: use of partially moved value
--> $DIR/borrowck-move-and-move.rs:27:9
|
LL | match [u(), u(), u(), u()] {
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
LL | xs @ [a, .., b] => {}
| -------------^-
| | |
| | value used here after move
| value moved here
| ^^^^^^-^^^^^^^^
| | |
| | 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[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:31:18
error[E0382]: use of partially moved value
--> $DIR/borrowck-move-and-move.rs:31:9
|
LL | match [u(), u(), u(), u()] {
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
LL | xs @ [_, ys @ .., _] => {}
| ---------^^^^^^^----
| ^^^^^^^^^-------^^^^
| | |
| | value used here after move
| value moved here
| | 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[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:24:16
--> $DIR/borrowck-move-and-move.rs:24:12
|
LL | fn fun(a @ b: U) {}
| ----^
| ^^^^-
| | |
| | value used here after move
| value moved here
| | 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
Expand Down
16 changes: 7 additions & 9 deletions src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,53 +18,51 @@ fn nc() -> NC {

fn main() {
let a @ box &b = Box::new(&C);
//~^ ERROR use of moved value

let a @ box b = Box::new(C);
//~^ ERROR use of moved value

fn f1(a @ box &b: Box<&C>) {}
//~^ ERROR use of moved value

fn f2(a @ box b: Box<C>) {}
//~^ ERROR use of moved value

match Box::new(C) {
a @ box b => {} //~ ERROR use of moved value
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 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 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 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 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);
}
Expand Down
Loading

0 comments on commit c93d25b

Please sign in to comment.