Rollup merge of #52907 - pnkfelix:issue-52877-original-source-should-precede-suggestions, r=petrochenkov

NLL: On "cannot move out of type" error, print original before rewrite

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:
```rust
    /// 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.

Fix #52877
This commit is contained in:
Pietro Albini 2018-08-01 10:13:06 +02:00 committed by GitHub
commit 14546cd501
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 44 deletions

View file

@ -341,7 +341,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
// another match arm // another match arm
binds_to.sort(); binds_to.sort();
binds_to.dedup(); binds_to.dedup();
for local in binds_to { let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
for (j, local) in binds_to.into_iter().enumerate() {
let bind_to = &self.mir.local_decls[local]; let bind_to = &self.mir.local_decls[local];
let binding_span = bind_to.source_info.span; let binding_span = bind_to.source_info.span;
@ -350,13 +351,15 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
Mutability::Not => "ref", Mutability::Not => "ref",
Mutability::Mut => "ref mut", Mutability::Mut => "ref mut",
}; };
if j == 0 {
err.span_label(binding_span, format!("data moved here"));
} else {
err.span_label(binding_span, format!("... and here"));
}
match bind_to.name { match bind_to.name {
Some(name) => { Some(name) => {
err.span_suggestion( multipart_suggestion.push((binding_span,
binding_span, format!("{} {}", ref_kind, name)));
"to prevent move, use ref or ref mut",
format!("{} {:?}", ref_kind, name),
);
} }
None => { None => {
err.span_label( err.span_label(
@ -366,6 +369,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
} }
} }
} }
err.multipart_suggestion("to prevent move, use ref or ref mut",
multipart_suggestion);
} }
// Nothing to suggest. // Nothing to suggest.
GroupedMoveError::OtherIllegalMove { .. } => (), GroupedMoveError::OtherIllegalMove { .. } => (),

View file

@ -19,14 +19,16 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
| |
LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) { LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
...
LL | f: _s,
| -- data moved here
LL | g: _t
| -- ... and here
help: to prevent move, use ref or ref mut help: to prevent move, use ref or ref mut
| |
LL | f: ref _s, LL | f: ref _s,
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | g: ref _t LL | g: ref _t
| ^^^^^^ |
error[E0507]: cannot move out of borrowed content error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-error-with-note.rs:57:11 --> $DIR/borrowck-move-error-with-note.rs:57:11

View file

@ -3,14 +3,19 @@ error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
| |
LL | match tail { LL | match tail {
| ^^^^ cannot move out of here | ^^^^ cannot move out of here
LL | &[Foo { string: a },
| - data moved here
...
LL | Foo { string: b }] => {
| - ... and here
help: to prevent move, use ref or ref mut help: to prevent move, use ref or ref mut
| |
LL | &[Foo { string: ref a }, LL | &[Foo { string: ref a },
| ^^^^^ LL | //~^ ERROR cannot move out of type `[Foo]`
help: to prevent move, use ref or ref mut LL | //~| cannot move out
| LL | //~| to prevent move
LL | Foo { string: ref b }] => { LL | Foo { string: ref b }] => {
| ^^^^^ |
error: aborting due to previous error error: aborting due to previous error

View file

@ -28,7 +28,10 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
LL | match vec { LL | match vec {
| ^^^ cannot move out of here | ^^^ cannot move out of here
LL | &mut [_a, //~ ERROR cannot move out LL | &mut [_a, //~ ERROR cannot move out
| -- help: to prevent move, use ref or ref mut: `ref _a` | --
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref _a`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:57:13 --> $DIR/borrowck-vec-pattern-nesting.rs:57:13
@ -46,7 +49,10 @@ LL | match vec {
| ^^^ cannot move out of here | ^^^ cannot move out of here
... ...
LL | _b] => {} LL | _b] => {}
| -- help: to prevent move, use ref or ref mut: `ref _b` | --
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref _b`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:70:13 --> $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
| |
LL | match vec { LL | match vec {
| ^^^ cannot move out of here | ^^^ cannot move out of here
LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out
| -- -- -- ... and here
| | |
| | ... and here
| data moved here
help: to prevent move, use ref or ref mut help: to prevent move, use ref or ref mut
| |
LL | &mut [ref _a, _b, _c] => {} //~ ERROR cannot move out LL | &mut [ref _a, ref _b, ref _c] => {} //~ ERROR cannot move out
| ^^^^^^ | ^^^^^^ ^^^^^^ ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | &mut [_a, ref _b, _c] => {} //~ ERROR cannot move out
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | &mut [_a, _b, ref _c] => {} //~ ERROR cannot move out
| ^^^^^^
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:82:13 --> $DIR/borrowck-vec-pattern-nesting.rs:82:13

View file

@ -4,6 +4,7 @@ error[E0507]: cannot move out of borrowed content
LL | let opt = a.iter().enumerate().find(|(_, &s)| { LL | let opt = a.iter().enumerate().find(|(_, &s)| {
| ^^^^^-^ | ^^^^^-^
| | | | | |
| | data moved here
| | help: to prevent move, use ref or ref mut: `ref s` | | help: to prevent move, use ref or ref mut: `ref s`
| cannot move out of borrowed content | cannot move out of borrowed content

View file

@ -4,7 +4,10 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
LL | match (S {f:"foo".to_string()}) { LL | match (S {f:"foo".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
LL | S {f:_s} => {} //~ ERROR cannot move out LL | S {f:_s} => {} //~ ERROR cannot move out
| -- help: to prevent move, use ref or ref mut: `ref _s` | --
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref _s`
error: aborting due to previous error error: aborting due to previous error

View file

@ -3,28 +3,40 @@ error[E0508]: cannot move out of type `[T]`, a non-copy slice
| |
LL | match (l1, l2) { LL | match (l1, l2) {
| ^^^^^^^^ cannot move out of here | ^^^^^^^^ cannot move out of here
LL | (&[], &[]) => println!("both empty"),
LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
| -- data moved here
...
LL | (&[hd1, ..], &[hd2, ..])
| --- ... and here
help: to prevent move, use ref or ref mut help: to prevent move, use ref or ref mut
| |
LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
| ^^^^^^ LL | => println!("one empty"),
help: to prevent move, use ref or ref mut LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
| LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
LL | (&[hd1, ..], &[ref hd2, ..]) LL | (&[hd1, ..], &[ref hd2, ..])
| ^^^^^^^ |
error[E0508]: cannot move out of type `[T]`, a non-copy slice error[E0508]: cannot move out of type `[T]`, a non-copy slice
--> $DIR/issue-12567.rs:14:11 --> $DIR/issue-12567.rs:14:11
| |
LL | match (l1, l2) { LL | match (l1, l2) {
| ^^^^^^^^ cannot move out of here | ^^^^^^^^ cannot move out of here
LL | (&[], &[]) => println!("both empty"),
LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
| -- data moved here
...
LL | (&[hd1, ..], &[hd2, ..])
| --- ... and here
help: to prevent move, use ref or ref mut help: to prevent move, use ref or ref mut
| |
LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
| ^^^^^^ LL | => println!("one empty"),
help: to prevent move, use ref or ref mut LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
| LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
LL | (&[ref hd1, ..], &[hd2, ..]) LL | (&[ref hd1, ..], &[hd2, ..])
| ^^^^^^^ |
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -59,6 +59,7 @@ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
LL | let C(D(s)) = c; LL | let C(D(s)) = c;
| - ^ cannot move out of here | - ^ cannot move out of here
| | | |
| data moved here
| help: to prevent move, use ref or ref mut: `ref s` | help: to prevent move, use ref or ref mut: `ref s`
error[E0507]: cannot move out of borrowed content error[E0507]: cannot move out of borrowed content
@ -88,7 +89,10 @@ LL | match x {
| ^ cannot move out of here | ^ cannot move out of here
... ...
LL | B::U(D(s)) => (), LL | B::U(D(s)) => (),
| - help: to prevent move, use ref or ref mut: `ref s` | -
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref s`
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:105:11 --> $DIR/move-errors.rs:105:11
@ -97,7 +101,10 @@ LL | match x {
| ^ cannot move out of here | ^ cannot move out of here
... ...
LL | (D(s), &t) => (), LL | (D(s), &t) => (),
| - help: to prevent move, use ref or ref mut: `ref s` | -
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref s`
error[E0507]: cannot move out of borrowed content error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:105:11 --> $DIR/move-errors.rs:105:11
@ -106,21 +113,25 @@ LL | match x {
| ^ cannot move out of borrowed content | ^ cannot move out of borrowed content
... ...
LL | (D(s), &t) => (), LL | (D(s), &t) => (),
| - help: to prevent move, use ref or ref mut: `ref t` | -
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref t`
error[E0509]: cannot move out of type `F`, which implements the `Drop` trait error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
--> $DIR/move-errors.rs:115:11 --> $DIR/move-errors.rs:115:11
| |
LL | match x { LL | match x {
| ^ cannot move out of here | ^ cannot move out of here
LL | //~^ ERROR
LL | F(s, mut t) => (),
| - ----- ... and here
| |
| data moved here
help: to prevent move, use ref or ref mut help: to prevent move, use ref or ref mut
| |
LL | F(ref s, mut t) => (), LL | F(ref s, ref mut t) => (),
| ^^^^^ | ^^^^^ ^^^^^^^^^
help: to prevent move, use ref or ref mut
|
LL | F(s, ref mut t) => (),
| ^^^^^^^^^
error[E0507]: cannot move out of borrowed content error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:123:11 --> $DIR/move-errors.rs:123:11