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

For move errors, suggest match ergonomics instead of ref #53147

Merged
merged 27 commits into from
Aug 16, 2018

Conversation

ashtneoi
Copy link
Contributor

@ashtneoi ashtneoi commented Aug 7, 2018

Partially fixes issue #52423. Also makes errors and suggestions more consistent between move-from-place and move-from-value errors.

Limitations:

  • Only the first pattern in a match arm can have a "consider removing this borrow operator" suggestion.
  • Suggestions don't always compile as-is (see the TODOs in the test for details).

Sorry for the really long test. I wanted to make sure I handled every case I could think of, and it turned out there were a lot of them.

Questions:

  • Is there any particular applicability I should set on those suggestions?
  • Are the notes about the Copy trait excessive?

@rust-highfive
Copy link
Collaborator

r? @cramertj

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 7, 2018
@ashtneoi
Copy link
Contributor Author

ashtneoi commented Aug 7, 2018

There are still tests to fix and bless, but I figured I'd see if this is the right idea before I start on that.

@rust-highfive

This comment has been minimized.

}
err.span_suggestion(
pat_span,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change this span to point at the span of the &/&mut rather than the whole pattern? I think it would make it more clear exactly what you're suggesting to remove.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although that would mean that the "suggestion" now points at the wrong place, meaning that the applicability would need to indicate that it was intended to be read and performed by a human. Perhaps leaving as-is but making the change to the error message I suggested below would be better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, changing the help message looks like it would be clear enough. Good call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could synthesize a new span from pat_span by looking at it's string constents and remove the leading &, whitespace, mut (when appropriate) and any further whitespace. Once we've done that, we can create a new span that points at sp.lo()~sp.hi()-snippet.len(). (I don't think that this is something urgent to do in this PR.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, thanks for reminding me about the whitespace between & and mut.

}
err.span_suggestion(
pat_span,
"consider removing this borrow operator",
Copy link
Member

@cramertj cramertj Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: perhaps "consider removing the &" / "consider removing the &mut" would be clearer than "consider removing this borrow operator"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the suggestion next to it it works as an introduction to the jargon that is sadly used in other places. The suggestion code should be enough to make it clear what we're telling the user to do, despite the jargon. That being said, the text could be "consider not borrowing here".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO "consider removing this borrow operator: Foo::Bar(..)" looks confusing, since "this" makes it sound like it's referring to Foo::Bar(..) as a "borrow operator", which isn't what's going on. I personally find "consider removing the &: Foo::Bar(...)" easier to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the (probably rare) case where the pattern is a double reference (&&Foo::Bar(..)), "consider not borrowing" would be sorta imprecise. But that might not be worth worrying about.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although, now that I think about it, I guess we could strip all the leading &/&mut instead of just the first one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is if we don't change the span either. If we do, this could look like this:

error[E0507]: cannot move out of borrowed content
  --> $DIR/dont-suggest-ref.rs:103:18
   |
LL |     let &X(_t) = s;
   |         -  --    ^ cannot move out of borrowed content
   |         |  |
   |         |  data moved here
   |         |  move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
   |         help: consider removing this borrow

@cramertj
Copy link
Member

cramertj commented Aug 7, 2018

This looks great to me so far! Thanks so much for doing this-- I'm really excited about these new errors.

Is there any particular applicability I should set on those suggestions?

It seems like they're MachineApplicable to me, but @estebank would know better what are guidelines are for when something is rigorous enough to be considered MachineApplicable.

Are the notes about the Copy trait excessive?

I think it seems reasonable to make a note about Copy (although the current "cannot move out of borrowed content" error does not), but IMO re-showing the span results in too much vertical space usage. Perhaps the span_note in move_error_labels could be made into a plain note instead?

_ => false,
},

err.span_note(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one

Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any particular applicability I should set on those suggestions?

The examples seem to be machine applicable. That being said, I am slightly worried about knock on effects on code after this error that is expecting a mutable borrow, for example. After applying the changes you will see new errors. This is fine most of the time, but it is less than ideal. I would go for MachineApplicable for now.

err.span_note(
binding_span,
&format!(
"move occurs because {} has type `{}`, \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move occurs because `{}`

}
err.span_suggestion(
pat_span,
"consider removing this borrow operator",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the suggestion next to it it works as an introduction to the jargon that is sadly used in other places. The suggestion code should be enough to make it clear what we're telling the user to do, despite the jargon. That being said, the text could be "consider not borrowing here".

}
err.span_suggestion(
pat_span,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could synthesize a new span from pat_span by looking at it's string constents and remove the leading &, whitespace, mut (when appropriate) and any further whitespace. Once we've done that, we can create a new span that points at sp.lo()~sp.hi()-snippet.len(). (I don't think that this is something urgent to do in this PR.)

@ashtneoi
Copy link
Contributor Author

ashtneoi commented Aug 7, 2018

Just realized that when destructuring a tuple, array, or struct, you end up with duplicate suggestions. Here's an example:

#![feature(nll)]

struct X {
    a: String,
    b: String,
}

fn main() {
    let x = X {
        a: String::new(),
        b: String::new(),
    };
    let &X { a, b } = &x;
}
error[E0507]: cannot move out of borrowed content
  --> a.rs:13:23
   |
13 |     let &X { a, b } = &x;
   |              -  -     ^^ cannot move out of borrowed content
   |              |  |
   |              |  ... and here
   |              data moved here
   |
note: move occurs because a has type `std::string::String`, which does not implement the `Copy` trait
  --> a.rs:13:14
   |
13 |     let &X { a, b } = &x;
   |              ^
note: move occurs because b has type `std::string::String`, which does not implement the `Copy` trait
  --> a.rs:13:17
   |
13 |     let &X { a, b } = &x;
   |                 ^
help: consider removing this borrow operator
   |
13 |     let X { a, b } = &x;
   |         ^^^^^^^^^^
help: consider removing this borrow operator
   |
13 |     let X { a, b } = &x;
   |         ^^^^^^^^^^

I'm guessing I should probably collect them together and dedup them based on their span?

@estebank
Copy link
Contributor

estebank commented Aug 7, 2018

I'm guessing I should probably collect them together and dedup them based on their span?

That would be a great idea, and also present:

note: move occurs because `a` has type `std::string::String` and `b` has type `std::string::String`, which do not implement the `Copy` trait
  --> a.rs:13:14
   |
13 |     let &X { a, b } = &x;
   |              ^  ^

@ashtneoi
Copy link
Contributor Author

ashtneoi commented Aug 7, 2018

Also it turns out I messed up the logic for derefs that don't start with * (as with index expressions)---it should fall back to adding &, not just give up.

Edit: fixed.

@cramertj
Copy link
Member

cramertj commented Aug 7, 2018

r? @estebank -- they know diagnostics better than I, and I've given what feedback I had to offer.

@rust-highfive rust-highfive assigned estebank and unassigned cramertj Aug 7, 2018
@ashtneoi
Copy link
Contributor Author

ashtneoi commented Aug 7, 2018

@cramertj Thanks for your help!

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@estebank estebank added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 9, 2018
@ashtneoi ashtneoi force-pushed the dont-suggest-ref branch 2 times, most recently from 60b3e5e to 76d40fc Compare August 12, 2018 20:34
@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@estebank

This comment has been minimized.

@ashtneoi
Copy link
Contributor Author

So I'm a little worried about combining the Copy notes into one, since if there's more than two or three vars then the note will end up being really long ("move occurs because a has type std::string::String, b has type std::string::String, c has type std::string::String, d has type std::string::String, ..."). Maybe something more like

note: move occurs because these variables have types which do not implement the `Copy` trait
  --> a.rs:13:14
   |
13 |     let &X { a, b } = &x;
   |              ^  ^

It might also be nice to add a label on each variable showing its type, but I guess that would end up being verbose again.

@estebank
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Aug 16, 2018

📌 Commit f4229b8 has been approved by estebank

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 16, 2018
@bors
Copy link
Contributor

bors commented Aug 16, 2018

⌛ Testing commit f4229b8 with merge 894c01f23b458da53696ae5bef2213d44ac208f3...

@bors
Copy link
Contributor

bors commented Aug 16, 2018

💔 Test failed - status-travis

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 16, 2018
@ashtneoi
Copy link
Contributor Author

Looks like this is just #53332 on Travis' end. Hopefully splitting the test into more pieces will help, and I'll take a look at fixing #53332 when I'm able.

@estebank
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Aug 16, 2018

📌 Commit 0023dd9 has been approved by estebank

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 16, 2018
@bors
Copy link
Contributor

bors commented Aug 16, 2018

⌛ Testing commit 0023dd9 with merge 142bb27...

bors added a commit that referenced this pull request Aug 16, 2018
For move errors, suggest match ergonomics instead of `ref`

Partially fixes issue #52423. Also makes errors and suggestions more consistent between move-from-place and move-from-value errors.

Limitations:
- Only the first pattern in a match arm can have a "consider removing this borrow operator" suggestion.
- Suggestions don't always compile as-is (see the TODOs in the test for details).

Sorry for the really long test. I wanted to make sure I handled every case I could think of, and it turned out there were a lot of them.

Questions:
- Is there any particular applicability I should set on those suggestions?
- Are the notes about the `Copy` trait excessive?
@bors
Copy link
Contributor

bors commented Aug 16, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: estebank
Pushing 142bb27 to master...

@bors bors merged commit 0023dd9 into rust-lang:master Aug 16, 2018
@ashtneoi ashtneoi deleted the dont-suggest-ref branch August 8, 2020 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants