Skip to content

Commit a5a3f76

Browse files
committed
NLL: On "cannot move out of type" error, print original source before rewrite.
* Arguably this change is sometimes injecting noise into the output (namely in the cases where the suggested rewrite is inline with the suggestion and we end up highlighting the original source code). I would not be opposed to something more aggressive/dynamic, like revising the suggestion code to automatically print the original source when necessary (e.g. when the error does not have a span that includes the span of the suggestion). * Also, as another note on this change: The doc comment for `Diagnostic::span_suggestion` says: /// The message /// /// * should not end in any punctuation (a `:` is added automatically) /// * should not be a question /// * should not contain any parts like "the following", "as shown" but the `:` is *not* added when the emitted line appears out-of-line relative to the suggestion. I find that to be an unfortunate UI experience. ---- As a drive-by fix, also changed code to combine multiple suggestions for a pattern into a single multipart suggestion (which vastly improves user experience IMO). ---- Includes the updates to expected NLL diagnostics.
1 parent 8961132 commit a5a3f76

8 files changed

+86
-44
lines changed

src/librustc_mir/borrow_check/move_errors.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
341341
// another match arm
342342
binds_to.sort();
343343
binds_to.dedup();
344-
for local in binds_to {
344+
let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
345+
for (j, local) in binds_to.into_iter().enumerate() {
345346
let bind_to = &self.mir.local_decls[local];
346347
let binding_span = bind_to.source_info.span;
347348

@@ -350,13 +351,15 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
350351
Mutability::Not => "ref",
351352
Mutability::Mut => "ref mut",
352353
};
354+
if j == 0 {
355+
err.span_label(binding_span, format!("data moved here"));
356+
} else {
357+
err.span_label(binding_span, format!("... and here"));
358+
}
353359
match bind_to.name {
354360
Some(name) => {
355-
err.span_suggestion(
356-
binding_span,
357-
"to prevent move, use ref or ref mut",
358-
format!("{} {:?}", ref_kind, name),
359-
);
361+
multipart_suggestion.push((binding_span,
362+
format!("{} {}", ref_kind, name)));
360363
}
361364
None => {
362365
err.span_label(
@@ -366,6 +369,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
366369
}
367370
}
368371
}
372+
err.multipart_suggestion("to prevent move, use ref or ref mut",
373+
multipart_suggestion);
369374
}
370375
// Nothing to suggest.
371376
GroupedMoveError::OtherIllegalMove { .. } => (),

src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
1919
|
2020
LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) {
2121
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
22+
...
23+
LL | f: _s,
24+
| -- data moved here
25+
LL | g: _t
26+
| -- ... and here
2227
help: to prevent move, use ref or ref mut
2328
|
2429
LL | f: ref _s,
25-
| ^^^^^^
26-
help: to prevent move, use ref or ref mut
27-
|
2830
LL | g: ref _t
29-
| ^^^^^^
31+
|
3032

3133
error[E0507]: cannot move out of borrowed content
3234
--> $DIR/borrowck-move-error-with-note.rs:57:11

src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr

+9-4
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@ error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
33
|
44
LL | match tail {
55
| ^^^^ cannot move out of here
6+
LL | &[Foo { string: a },
7+
| - data moved here
8+
...
9+
LL | Foo { string: b }] => {
10+
| - ... and here
611
help: to prevent move, use ref or ref mut
712
|
813
LL | &[Foo { string: ref a },
9-
| ^^^^^
10-
help: to prevent move, use ref or ref mut
11-
|
14+
LL | //~^ ERROR cannot move out of type `[Foo]`
15+
LL | //~| cannot move out
16+
LL | //~| to prevent move
1217
LL | Foo { string: ref b }] => {
13-
| ^^^^^
18+
|
1419

1520
error: aborting due to previous error
1621

src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr

+15-12
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
2828
LL | match vec {
2929
| ^^^ cannot move out of here
3030
LL | &mut [_a, //~ ERROR cannot move out
31-
| -- help: to prevent move, use ref or ref mut: `ref _a`
31+
| --
32+
| |
33+
| data moved here
34+
| help: to prevent move, use ref or ref mut: `ref _a`
3235

3336
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
3437
--> $DIR/borrowck-vec-pattern-nesting.rs:57:13
@@ -46,7 +49,10 @@ LL | match vec {
4649
| ^^^ cannot move out of here
4750
...
4851
LL | _b] => {}
49-
| -- help: to prevent move, use ref or ref mut: `ref _b`
52+
| --
53+
| |
54+
| data moved here
55+
| help: to prevent move, use ref or ref mut: `ref _b`
5056

5157
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
5258
--> $DIR/borrowck-vec-pattern-nesting.rs:70:13
@@ -62,18 +68,15 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
6268
|
6369
LL | match vec {
6470
| ^^^ cannot move out of here
71+
LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out
72+
| -- -- -- ... and here
73+
| | |
74+
| | ... and here
75+
| data moved here
6576
help: to prevent move, use ref or ref mut
6677
|
67-
LL | &mut [ref _a, _b, _c] => {} //~ ERROR cannot move out
68-
| ^^^^^^
69-
help: to prevent move, use ref or ref mut
70-
|
71-
LL | &mut [_a, ref _b, _c] => {} //~ ERROR cannot move out
72-
| ^^^^^^
73-
help: to prevent move, use ref or ref mut
74-
|
75-
LL | &mut [_a, _b, ref _c] => {} //~ ERROR cannot move out
76-
| ^^^^^^
78+
LL | &mut [ref _a, ref _b, ref _c] => {} //~ ERROR cannot move out
79+
| ^^^^^^ ^^^^^^ ^^^^^^
7780

7881
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
7982
--> $DIR/borrowck-vec-pattern-nesting.rs:82:13

src/test/ui/borrowck/issue-51415.nll.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0507]: cannot move out of borrowed content
44
LL | let opt = a.iter().enumerate().find(|(_, &s)| {
55
| ^^^^^-^
66
| | |
7+
| | data moved here
78
| | help: to prevent move, use ref or ref mut: `ref s`
89
| cannot move out of borrowed content
910

src/test/ui/codemap_tests/overlapping_spans.nll.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
44
LL | match (S {f:"foo".to_string()}) {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
66
LL | S {f:_s} => {} //~ ERROR cannot move out
7-
| -- help: to prevent move, use ref or ref mut: `ref _s`
7+
| --
8+
| |
9+
| data moved here
10+
| help: to prevent move, use ref or ref mut: `ref _s`
811

912
error: aborting due to previous error
1013

src/test/ui/issue-12567.nll.stderr

+20-8
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,40 @@ error[E0508]: cannot move out of type `[T]`, a non-copy slice
33
|
44
LL | match (l1, l2) {
55
| ^^^^^^^^ cannot move out of here
6+
LL | (&[], &[]) => println!("both empty"),
7+
LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
8+
| -- data moved here
9+
...
10+
LL | (&[hd1, ..], &[hd2, ..])
11+
| --- ... and here
612
help: to prevent move, use ref or ref mut
713
|
814
LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
9-
| ^^^^^^
10-
help: to prevent move, use ref or ref mut
11-
|
15+
LL | => println!("one empty"),
16+
LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
17+
LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
1218
LL | (&[hd1, ..], &[ref hd2, ..])
13-
| ^^^^^^^
19+
|
1420

1521
error[E0508]: cannot move out of type `[T]`, a non-copy slice
1622
--> $DIR/issue-12567.rs:14:11
1723
|
1824
LL | match (l1, l2) {
1925
| ^^^^^^^^ cannot move out of here
26+
LL | (&[], &[]) => println!("both empty"),
27+
LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
28+
| -- data moved here
29+
...
30+
LL | (&[hd1, ..], &[hd2, ..])
31+
| --- ... and here
2032
help: to prevent move, use ref or ref mut
2133
|
2234
LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
23-
| ^^^^^^
24-
help: to prevent move, use ref or ref mut
25-
|
35+
LL | => println!("one empty"),
36+
LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
37+
LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
2638
LL | (&[ref hd1, ..], &[hd2, ..])
27-
| ^^^^^^^
39+
|
2840

2941
error: aborting due to 2 previous errors
3042

src/test/ui/nll/move-errors.stderr

+20-9
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
5959
LL | let C(D(s)) = c;
6060
| - ^ cannot move out of here
6161
| |
62+
| data moved here
6263
| help: to prevent move, use ref or ref mut: `ref s`
6364

6465
error[E0507]: cannot move out of borrowed content
@@ -88,7 +89,10 @@ LL | match x {
8889
| ^ cannot move out of here
8990
...
9091
LL | B::U(D(s)) => (),
91-
| - help: to prevent move, use ref or ref mut: `ref s`
92+
| -
93+
| |
94+
| data moved here
95+
| help: to prevent move, use ref or ref mut: `ref s`
9296

9397
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
9498
--> $DIR/move-errors.rs:105:11
@@ -97,7 +101,10 @@ LL | match x {
97101
| ^ cannot move out of here
98102
...
99103
LL | (D(s), &t) => (),
100-
| - help: to prevent move, use ref or ref mut: `ref s`
104+
| -
105+
| |
106+
| data moved here
107+
| help: to prevent move, use ref or ref mut: `ref s`
101108

102109
error[E0507]: cannot move out of borrowed content
103110
--> $DIR/move-errors.rs:105:11
@@ -106,21 +113,25 @@ LL | match x {
106113
| ^ cannot move out of borrowed content
107114
...
108115
LL | (D(s), &t) => (),
109-
| - help: to prevent move, use ref or ref mut: `ref t`
116+
| -
117+
| |
118+
| data moved here
119+
| help: to prevent move, use ref or ref mut: `ref t`
110120

111121
error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
112122
--> $DIR/move-errors.rs:115:11
113123
|
114124
LL | match x {
115125
| ^ cannot move out of here
126+
LL | //~^ ERROR
127+
LL | F(s, mut t) => (),
128+
| - ----- ... and here
129+
| |
130+
| data moved here
116131
help: to prevent move, use ref or ref mut
117132
|
118-
LL | F(ref s, mut t) => (),
119-
| ^^^^^
120-
help: to prevent move, use ref or ref mut
121-
|
122-
LL | F(s, ref mut t) => (),
123-
| ^^^^^^^^^
133+
LL | F(ref s, ref mut t) => (),
134+
| ^^^^^ ^^^^^^^^^
124135

125136
error[E0507]: cannot move out of borrowed content
126137
--> $DIR/move-errors.rs:123:11

0 commit comments

Comments
 (0)