Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reverse binding order in matches to allow the subbinding of copyable fields in bindings after @ #78638

Merged
merged 7 commits into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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