Skip to content

Commit 5faf657

Browse files
committed
Change heuristic and add tests
1 parent a10e07c commit 5faf657

9 files changed

+125
-9
lines changed

Diff for: src/librustc_mir/borrow_check/diagnostics/mod.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -776,13 +776,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
776776
}
777777
}
778778

779-
let normal_ret = if let [ProjectionElem::Downcast(..), ProjectionElem::Field(_, _)] =
780-
moved_place.projection
781-
{
782-
PatUse(stmt.source_info.span)
783-
} else {
784-
OtherUse(stmt.source_info.span)
785-
};
779+
let normal_ret =
780+
if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
781+
PatUse(stmt.source_info.span)
782+
} else {
783+
OtherUse(stmt.source_info.span)
784+
};
786785

787786
// We are trying to find MIR of the form:
788787
// ```

Diff for: src/test/ui/borrowck/move-in-pattern-mut.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Issue #63988
2+
#[derive(Debug)]
3+
struct S;
4+
fn foo(_: Option<S>) {}
5+
6+
enum E {
7+
V {
8+
s: S,
9+
}
10+
}
11+
fn bar(_: E) {}
12+
13+
fn main() {
14+
let s = Some(S);
15+
if let Some(mut x) = s {
16+
x = S;
17+
}
18+
foo(s); //~ ERROR use of moved value: `s`
19+
let mut e = E::V { s: S };
20+
let E::V { s: mut x } = e;
21+
x = S;
22+
bar(e); //~ ERROR use of moved value: `e`
23+
}

Diff for: src/test/ui/borrowck/move-in-pattern-mut.stderr

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error[E0382]: use of moved value: `s`
2+
--> $DIR/move-in-pattern-mut.rs:18:9
3+
|
4+
LL | if let Some(mut x) = s {
5+
| ----- value moved here
6+
...
7+
LL | foo(s);
8+
| ^ value used here after partial move
9+
|
10+
= note: move occurs because value has type `S`, which does not implement the `Copy` trait
11+
help: borrow this field in the pattern to avoid moving `s.0`
12+
|
13+
LL | if let Some(ref mut x) = s {
14+
| ^^^
15+
16+
error[E0382]: use of moved value: `e`
17+
--> $DIR/move-in-pattern-mut.rs:22:9
18+
|
19+
LL | let E::V { s: mut x } = e;
20+
| ----- value moved here
21+
LL | x = S;
22+
LL | bar(e);
23+
| ^ value used here after partial move
24+
|
25+
= note: move occurs because value has type `S`, which does not implement the `Copy` trait
26+
help: borrow this field in the pattern to avoid moving `e.s`
27+
|
28+
LL | let E::V { s: ref mut x } = e;
29+
| ^^^
30+
31+
error: aborting due to 2 previous errors
32+
33+
For more information about this error, try `rustc --explain E0382`.

Diff for: src/test/ui/borrowck/move-in-pattern.fixed

+11
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
struct S;
55
fn foo(_: Option<S>) {}
66

7+
enum E {
8+
V {
9+
s: S,
10+
}
11+
}
12+
fn bar(_: E) {}
13+
714
fn main() {
815
let s = Some(S);
916
if let Some(ref x) = s {
1017
let _ = x;
1118
}
1219
foo(s); //~ ERROR use of moved value: `s`
20+
let e = E::V { s: S };
21+
let E::V { s: ref x } = e;
22+
let _ = x;
23+
bar(e); //~ ERROR use of moved value: `e`
1324
}

Diff for: src/test/ui/borrowck/move-in-pattern.rs

+11
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
struct S;
55
fn foo(_: Option<S>) {}
66

7+
enum E {
8+
V {
9+
s: S,
10+
}
11+
}
12+
fn bar(_: E) {}
13+
714
fn main() {
815
let s = Some(S);
916
if let Some(x) = s {
1017
let _ = x;
1118
}
1219
foo(s); //~ ERROR use of moved value: `s`
20+
let e = E::V { s: S };
21+
let E::V { s: x } = e;
22+
let _ = x;
23+
bar(e); //~ ERROR use of moved value: `e`
1324
}

Diff for: src/test/ui/borrowck/move-in-pattern.stderr

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `s`
2-
--> $DIR/move-in-pattern.rs:12:9
2+
--> $DIR/move-in-pattern.rs:19:9
33
|
44
LL | if let Some(x) = s {
55
| - value moved here
@@ -13,6 +13,21 @@ help: borrow this field in the pattern to avoid moving `s.0`
1313
LL | if let Some(ref x) = s {
1414
| ^^^
1515

16-
error: aborting due to previous error
16+
error[E0382]: use of moved value: `e`
17+
--> $DIR/move-in-pattern.rs:23:9
18+
|
19+
LL | let E::V { s: x } = e;
20+
| - value moved here
21+
LL | let _ = x;
22+
LL | bar(e);
23+
| ^ value used here after partial move
24+
|
25+
= note: move occurs because value has type `S`, which does not implement the `Copy` trait
26+
help: borrow this field in the pattern to avoid moving `e.s`
27+
|
28+
LL | let E::V { s: ref x } = e;
29+
| ^^^
30+
31+
error: aborting due to 2 previous errors
1732

1833
For more information about this error, try `rustc --explain E0382`.

Diff for: src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | consume(node) + r
88
| ^^^^ value used here after partial move
99
|
1010
= note: move occurs because value has type `std::boxed::Box<List>`, which does not implement the `Copy` trait
11+
help: borrow this field in the pattern to avoid moving `node.next.0`
12+
|
13+
LL | Some(ref right) => consume(right),
14+
| ^^^
1115

1216
error: aborting due to previous error
1317

Diff for: src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
357357
| value moved here
358358
|
359359
= note: move occurs because value has type `main::U`, which does not implement the `Copy` trait
360+
help: borrow this field in the pattern to avoid moving the value
361+
|
362+
LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
363+
| ^^^
360364

361365
error[E0382]: use of moved value
362366
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
@@ -379,6 +383,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
379383
| value moved here
380384
|
381385
= note: move occurs because value has type `main::U`, which does not implement the `Copy` trait
386+
help: borrow this field in the pattern to avoid moving the value
387+
|
388+
LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
389+
| ^^^
382390

383391
error[E0382]: borrow of moved value
384392
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30
@@ -412,6 +420,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
412420
| value moved here
413421
|
414422
= note: move occurs because value has type `main::U`, which does not implement the `Copy` trait
423+
help: borrow this field in the pattern to avoid moving the value
424+
|
425+
LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
426+
| ^^^
415427

416428
error[E0382]: use of moved value
417429
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
@@ -434,6 +446,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
434446
| value moved here
435447
|
436448
= note: move occurs because value has type `main::U`, which does not implement the `Copy` trait
449+
help: borrow this field in the pattern to avoid moving the value
450+
|
451+
LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
452+
| ^^^
437453

438454
error[E0382]: borrow of moved value
439455
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30

Diff for: src/test/ui/ref-suggestion.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ LL | x;
2828
| ^ value used here after partial move
2929
|
3030
= note: move occurs because value has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
31+
help: borrow this field in the pattern to avoid moving `x.0.0`
32+
|
33+
LL | (Some(ref y), ()) => {},
34+
| ^^^
3135

3236
error: aborting due to 3 previous errors
3337

0 commit comments

Comments
 (0)