Skip to content

Add help message if a FnOnce is moved #41772

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

Merged
merged 1 commit into from
May 20, 2017

Conversation

GuillaumeGomez
Copy link
Member

@GuillaumeGomez GuillaumeGomez commented May 5, 2017

Fixes #40855.

r? @eddyb

| ^^^^^^^^^^^^^^^ value used here after move
|
= help: closure was moved because it only implements `FnOnce`
= note: move occurs because `debug_dump_dict` has type `[closure@$DIR/fn_once-moved.rs:15:27: 19:6 dict:std::collections::HashMap<i32, i32>]`, which does not implement the `Copy` trait
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this note be removed (only for this case)?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was wondering about this actually...

Copy link
Member

Choose a reason for hiding this comment

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

It does actually have some helpful information: std::collections::HashMap<i32, i32> ... Copy. I don't know if that's intentionally there, though...

Copy link
Member Author

Choose a reason for hiding this comment

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

I think we should better keep it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I think it should be removed. I highly doubt anyone will extract much value out of it -- particularly in non-trivial cases with more upvars. It'd be better to extend the upvar inference to track why a move is occurring, I suspect.

@GuillaumeGomez, interested in pursuing that?

21 | debug_dump_dict();
| ^^^^^^^^^^^^^^^ value used here after move
|
= help: closure was moved because it only implements `FnOnce`
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this point at the closure's span? If so, the text should be changed to something along the lines of

error[E0382]: use of moved value: `debug_dump_dict`
  --> $DIR/fn_once-moved.rs:21:5
15 |    let debug_dump_dict = || {
   |        --------------- closure only implements `FnOnce` so calling it moves it
...
20 |     debug_dump_dict();
   |     --------------- value moved here
21 |     debug_dump_dict();
   |     ^^^^^^^^^^^^^^^ value used here after move

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point!

@eddyb
Copy link
Member

eddyb commented May 6, 2017

r? @nikomatsakis

@rust-highfive rust-highfive assigned nikomatsakis and unassigned eddyb May 6, 2017
@Mark-Simulacrum Mark-Simulacrum added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 7, 2017
ty::TypeVariants::TyClosure(id, _) => {
if let Ok(ty::ClosureKind::FnOnce) =
ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
err.help("closure was moved because it only implements `FnOnce`");
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm. I'm torn. This message is definitely an improvement. I wonder if we can't do better. One thing that would be really nice is if we could show why the closure implements FnOnce (i.e., because it has a move from the environment, typically).

We would then say something like:

  • closure cannot be invoked twice because it moves the variable dict out of its environment

Computing this would require modifying upvar.rs to make the information available. But it seems worthwhile (it's been on my to-do list for a while). Possibly should be deferred to a separate PR, I'm not sure.

| ^^^^^^^^^^^^^^^ value used here after move
|
= help: closure was moved because it only implements `FnOnce`
= note: move occurs because `debug_dump_dict` has type `[closure@$DIR/fn_once-moved.rs:15:27: 19:6 dict:std::collections::HashMap<i32, i32>]`, which does not implement the `Copy` trait
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I think it should be removed. I highly doubt anyone will extract much value out of it -- particularly in non-trivial cases with more upvars. It'd be better to extend the upvar inference to track why a move is occurring, I suspect.

@GuillaumeGomez, interested in pursuing that?

@nikomatsakis
Copy link
Contributor

(To be clear, I'd be happy to mentor those changes.)

@GuillaumeGomez
Copy link
Member Author

Totally interested in pursuing it.

@nikomatsakis
Copy link
Contributor

@GuillaumeGomez shall we start by landing this PR, or you want to pursue in this PR?

The part of the code you have to look at a bit is in librustc_typeck/check/upvar.rs. This code basically walks the AST and observes what happens, gradually "bumping up" the closure-kind to be something more specific based on what it observes. Ultimately, these bumps occur by calls to adjust_closure_kind(). Right now, that method takes zero context as to why the bump occurred.

We would want to extend it with a span, I think. Then we could extend the temp_closure_kinds table to carry not only the closure kind but also the span that caused us to change it (and maybe a bit more info). We'd have to trace back to the callers to encode this span.

We'll also have to change the closure_kinds field of TypeckTables so that it maps not only to a ClosureKind but also the Span (and whatever else) that we are tracing through. This is a bit of a shame, since this info is only relevant in the local crate; I'm wondering then if we want to consider storing the span in some other place. But TypeckTables is realy going to be the most convenient place, so I think that's ultimately where I'd put it.

Question for @eddyb -- is it ok to have a Span in TypeckTables? Will the metadata code freak out? Should we avoid it?

@eddyb
Copy link
Member

eddyb commented May 16, 2017

Span is fine anywhere nowadays.

@GuillaumeGomez
Copy link
Member Author

@nikomatsakis: I think it'll take me quite some time to finish the full changes requested, so better merge this one and I'll open another one once I'll start. It'll allow me to not be bothered by master's changes too much.

@nikomatsakis
Copy link
Contributor

@GuillaumeGomez ok, I opened #42065 and copied mentoring instructions in there. Maybe you or someone else will pick it up.

I'd be happy to r+ this, except that I still think we should suppress the note that dumps the full type of the closure. It's just too much information and I think it's unhelpful.

@GuillaumeGomez
Copy link
Member Author

Ok, I'll remove it so we can move forward.

@GuillaumeGomez
Copy link
Member Author

Updated.

@estebank
Copy link
Contributor

@nikomatsakis approving

@bors r+

@bors
Copy link
Collaborator

bors commented May 19, 2017

📌 Commit 0c0d11b has been approved by estebank

@bors
Copy link
Collaborator

bors commented May 19, 2017

⌛ Testing commit 0c0d11b with merge 4662b15...

bors added a commit that referenced this pull request May 19, 2017
Add help message if a FnOnce is moved

Fixes #40855.

r? @eddyb
@bors
Copy link
Collaborator

bors commented May 20, 2017

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

@bors bors merged commit 0c0d11b into rust-lang:master May 20, 2017
@GuillaumeGomez GuillaumeGomez deleted the fn-once-message branch May 20, 2017 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants