Skip to content

Commit c93d25b

Browse files
committed
reverse binding order in matches ...
... to allow the subbinding of copyable fields in bindings after `@` Fixes #69971
1 parent 0d33ab7 commit c93d25b

21 files changed

+641
-709
lines changed

compiler/rustc_mir_build/src/build/matches/simplify.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
131131
}
132132

133133
PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
134-
candidate.bindings.push(Binding {
134+
// issue #69971: the binding order should be right to left if there are more
135+
// bindings after `@` to please the borrow checker
136+
// Ex
137+
// struct NonCopyStruct {
138+
// copy_field: u32,
139+
// }
140+
//
141+
// fn foo1(x: NonCopyStruct) {
142+
// let y @ NonCopyStruct { copy_field: z } = x;
143+
// // the above should turn into
144+
// let z = x.copy_field;
145+
// let y = x;
146+
// }
147+
candidate.bindings.insert(0, Binding {
135148
name,
136149
mutability,
137150
span: match_pair.pattern.span,

src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,28 @@ fn main() {
1212
let x = Some(X { x: () });
1313
match x {
1414
Some(ref _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed
15+
//~| ERROR borrow of moved value
1516
None => panic!(),
1617
}
1718

1819
let x = Some(X { x: () });
1920
match x {
2021
Some(_z @ ref _y) => {}
2122
//~^ ERROR borrow of moved value
22-
//~| ERROR borrow of moved value
2323
None => panic!(),
2424
}
2525

2626
let mut x = Some(X { x: () });
2727
match x {
2828
Some(ref mut _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed
29+
//~| ERROR borrow of moved value
2930
None => panic!(),
3031
}
3132

3233
let mut x = Some(X { x: () });
3334
match x {
3435
Some(_z @ ref mut _y) => {}
3536
//~^ ERROR borrow of moved value
36-
//~| ERROR borrow of moved value
3737
None => panic!(),
3838
}
3939
}

src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr

+18-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | Some(ref _y @ _z) => {}
88
| value borrowed, by `_y`, here
99

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

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

3939
error[E0382]: borrow of moved value
40-
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:19
40+
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
4141
|
42-
LL | Some(_z @ ref _y) => {}
43-
| -----^^^^^^
44-
| | |
45-
| | value borrowed here after move
46-
| value moved here
42+
LL | Some(ref _y @ _z) => {}
43+
| ^^^^^^^^^--
44+
| | |
45+
| | value moved here
46+
| value borrowed here after move
4747
|
4848
= note: move occurs because value has type `X`, which does not implement the `Copy` trait
4949
help: borrow this field in the pattern to avoid moving `x.0`
5050
|
51-
LL | Some(ref _z @ ref _y) => {}
52-
| ^^^
51+
LL | Some(ref _y @ ref _z) => {}
52+
| ^^^
5353

5454
error[E0382]: borrow of moved value
55-
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:19
55+
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
5656
|
57-
LL | Some(_z @ ref mut _y) => {}
58-
| -----^^^^^^^^^^
59-
| | |
60-
| | value borrowed here after move
61-
| value moved here
57+
LL | Some(ref mut _y @ _z) => {}
58+
| ^^^^^^^^^^^^^--
59+
| | |
60+
| | value moved here
61+
| value borrowed here after move
6262
|
6363
= note: move occurs because value has type `X`, which does not implement the `Copy` trait
6464
help: borrow this field in the pattern to avoid moving `x.0`
6565
|
66-
LL | Some(ref _z @ ref mut _y) => {}
67-
| ^^^
66+
LL | Some(ref mut _y @ ref _z) => {}
67+
| ^^^
6868

6969
error: aborting due to 6 previous errors
7070

src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn main() {}
77
struct A(Box<u8>);
88

99
fn f(a @ A(u): A) -> Box<u8> {
10-
//~^ ERROR use of moved value
10+
//~^ ERROR use of partially moved value
1111
drop(a);
1212
u
1313
}

src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
error[E0382]: use of moved value
2-
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:12
1+
error[E0382]: use of partially moved value
2+
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:6
33
|
44
LL | fn f(a @ A(u): A) -> Box<u8> {
5-
| ------^-
5+
| ^^^^^^-^
66
| | |
7-
| | value used here after move
8-
| value moved here
9-
| move occurs because value has type `A`, which does not implement the `Copy` trait
7+
| | value partially moved here
8+
| value used here after partial move
9+
|
10+
= note: partial move occurs because value has type `Box<u8>`, which does not implement the `Copy` trait
1011

1112
error: aborting due to previous error
1213

src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ fn main() {
1212

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

15-
let a @ (b, c) = (U, U); //~ ERROR use of moved value
15+
let a @ (b, c) = (U, U); //~ ERROR use of partially moved value
1616

17-
let a @ (b, c) = (u(), u()); //~ ERROR use of moved value
17+
let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value
1818

1919
match Ok(U) {
20-
a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value
21-
//~^ ERROR use of moved value
20+
a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of partially moved value
21+
//~^ ERROR use of partially moved value
2222
}
2323

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

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

3030
match [u(), u(), u(), u()] {
31-
xs @ [_, ys @ .., _] => {} //~ ERROR use of moved value
31+
xs @ [_, ys @ .., _] => {} //~ ERROR use of partially moved value
3232
}
3333
}

src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr

+61-49
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,94 @@
11
error[E0382]: use of moved value
2-
--> $DIR/borrowck-move-and-move.rs:13:13
2+
--> $DIR/borrowck-move-and-move.rs:13:9
33
|
44
LL | let a @ b = U;
5-
| ----^ - move occurs because value has type `U`, which does not implement the `Copy` trait
5+
| ^^^^- - move occurs because value has type `U`, which does not implement the `Copy` trait
66
| | |
7-
| | value used here after move
8-
| value moved here
7+
| | value moved here
8+
| value used here after move
99

10-
error[E0382]: use of moved value
11-
--> $DIR/borrowck-move-and-move.rs:15:17
10+
error[E0382]: use of partially moved value
11+
--> $DIR/borrowck-move-and-move.rs:15:9
1212
|
1313
LL | let a @ (b, c) = (U, U);
14-
| --------^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
15-
| | |
16-
| | value used here after move
17-
| value moved here
14+
| ^^^^^-^^^^
15+
| | |
16+
| | value partially moved here
17+
| value used here after partial move
18+
|
19+
= note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
1820

19-
error[E0382]: use of moved value
20-
--> $DIR/borrowck-move-and-move.rs:17:17
21+
error[E0382]: use of partially moved value
22+
--> $DIR/borrowck-move-and-move.rs:17:9
2123
|
2224
LL | let a @ (b, c) = (u(), u());
23-
| --------^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
24-
| | |
25-
| | value used here after move
26-
| value moved here
25+
| ^^^^^-^^^^
26+
| | |
27+
| | value partially moved here
28+
| value used here after partial move
29+
|
30+
= note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
2731

28-
error[E0382]: use of moved value
29-
--> $DIR/borrowck-move-and-move.rs:20:16
32+
error[E0382]: use of partially moved value
33+
--> $DIR/borrowck-move-and-move.rs:20:9
3034
|
31-
LL | match Ok(U) {
32-
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
3335
LL | a @ Ok(b) | a @ Err(b) => {}
34-
| -------^-
36+
| ^^^^^^^-^
3537
| | |
36-
| | value used here after move
37-
| value moved here
38+
| | value partially moved here
39+
| value used here after partial move
40+
|
41+
= note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
42+
help: borrow this field in the pattern to avoid moving the value
43+
|
44+
LL | a @ Ok(ref b) | a @ Err(b) => {}
45+
| ^^^
3846

39-
error[E0382]: use of moved value
40-
--> $DIR/borrowck-move-and-move.rs:20:29
47+
error[E0382]: use of partially moved value
48+
--> $DIR/borrowck-move-and-move.rs:20:21
4149
|
42-
LL | match Ok(U) {
43-
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
4450
LL | a @ Ok(b) | a @ Err(b) => {}
45-
| --------^-
51+
| ^^^^^^^^-^
4652
| | |
47-
| | value used here after move
48-
| value moved here
53+
| | value partially moved here
54+
| value used here after partial move
55+
|
56+
= note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
57+
help: borrow this field in the pattern to avoid moving the value
58+
|
59+
LL | a @ Ok(b) | a @ Err(ref b) => {}
60+
| ^^^
4961

50-
error[E0382]: use of moved value
51-
--> $DIR/borrowck-move-and-move.rs:27:22
62+
error[E0382]: use of partially moved value
63+
--> $DIR/borrowck-move-and-move.rs:27:9
5264
|
53-
LL | match [u(), u(), u(), u()] {
54-
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
5565
LL | xs @ [a, .., b] => {}
56-
| -------------^-
57-
| | |
58-
| | value used here after move
59-
| value moved here
66+
| ^^^^^^-^^^^^^^^
67+
| | |
68+
| | value partially moved here
69+
| value used here after partial move
70+
|
71+
= note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
6072

61-
error[E0382]: use of moved value
62-
--> $DIR/borrowck-move-and-move.rs:31:18
73+
error[E0382]: use of partially moved value
74+
--> $DIR/borrowck-move-and-move.rs:31:9
6375
|
64-
LL | match [u(), u(), u(), u()] {
65-
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
6676
LL | xs @ [_, ys @ .., _] => {}
67-
| ---------^^^^^^^----
77+
| ^^^^^^^^^-------^^^^
6878
| | |
69-
| | value used here after move
70-
| value moved here
79+
| | value partially moved here
80+
| value used here after partial move
81+
|
82+
= note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
7183

7284
error[E0382]: use of moved value
73-
--> $DIR/borrowck-move-and-move.rs:24:16
85+
--> $DIR/borrowck-move-and-move.rs:24:12
7486
|
7587
LL | fn fun(a @ b: U) {}
76-
| ----^
88+
| ^^^^-
7789
| | |
78-
| | value used here after move
79-
| value moved here
90+
| | value moved here
91+
| value used here after move
8092
| move occurs because value has type `U`, which does not implement the `Copy` trait
8193

8294
error: aborting due to 8 previous errors

src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -18,53 +18,51 @@ fn nc() -> NC {
1818

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

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

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

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

3228
match Box::new(C) {
33-
a @ box b => {} //~ ERROR use of moved value
29+
a @ box b => {}
3430
}
3531

3632
let ref a @ box b = Box::new(NC); //~ ERROR cannot move out of value because it is borrowed
33+
//~| ERROR borrow of moved value
3734

3835
let ref a @ box ref mut b = Box::new(nc());
3936
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
4037
let ref a @ box ref mut b = Box::new(NC);
4138
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
4239
let ref a @ box ref mut b = Box::new(NC);
4340
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
41+
//~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
4442
*b = NC;
4543
let ref a @ box ref mut b = Box::new(NC);
4644
//~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
47-
//~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
45+
//~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
4846
*b = NC;
4947
drop(a);
5048

5149
let ref mut a @ box ref b = Box::new(NC);
5250
//~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
53-
//~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
51+
//~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
5452
*a = Box::new(NC);
5553
drop(b);
5654

5755
fn f5(ref mut a @ box ref b: Box<NC>) {
5856
//~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
59-
//~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
57+
//~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
6058
*a = Box::new(NC);
6159
drop(b);
6260
}
6361

6462
match Box::new(nc()) {
6563
ref mut a @ box ref b => {
6664
//~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
67-
//~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
65+
//~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
6866
*a = Box::new(NC);
6967
drop(b);
7068
}

0 commit comments

Comments
 (0)