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

NLL does not allow closure to return a reference that it (maybe) should be able to return #51354

Closed
DutchGhost opened this issue Jun 4, 2018 · 4 comments
Labels
A-NLL Area: Non-lexical lifetimes (NLL) NLL-complete Working towards the "valid code works" goal T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Milestone

Comments

@DutchGhost
Copy link
Contributor

With nll turned on, the following code does not compile:
https://play.rust-lang.org/?gist=366e4fde473d02f294a527a462c9e7da&version=nightly&mode=debug

#![feature(nll)]

fn main() {
    let mut v: Vec<()> = Vec::new();
    
    'a: while break 'a {|| &mut v; }
}

Error message:

error: free region `` does not outlive free region `'_#1r`
 --> src/main.rs:6:28
  |
6 |     'a: while break 'a {|| &mut v; }
  |                            ^^^^^^

error: aborting due to previous error

error: Could not compile `playground`.

When not using the nll feature, it compiles.

@matthewjasper matthewjasper added the A-NLL Area: Non-lexical lifetimes (NLL) label Jun 4, 2018
@matthewjasper
Copy link
Contributor

I think this is intentional, as the closure can't be called, see #48238.

@DutchGhost
Copy link
Contributor Author

Ah, I see. But shouldn't it notice
the closure is unreachable because of the break inside the condition of the loop...?

@nikomatsakis
Copy link
Contributor

Ah, huh. Same errors without the loop:

#![feature(nll)]

fn main() {
    let mut v: Vec<()> = Vec::new();
    || &mut v;
}

I was going to tag this as a dup of #51027 but I'm not convinced we should be getting this error. The error is arising -- roughly -- because we are upset about returning the &mut v reference to the caller, but it seems like we should be able to return that reference.

Going to mark as Release Candidate.

@nikomatsakis nikomatsakis changed the title NLL free region ` does not outlive free region '_#1r` NLL does not allow closure to return a reference that it (maybe) should be able to return Jul 3, 2018
@nikomatsakis nikomatsakis added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-compiler-nll labels Jul 3, 2018
@pnkfelix pnkfelix added the NLL-complete Working towards the "valid code works" goal label Jul 24, 2018
@nikomatsakis
Copy link
Contributor

This is a duplicate of #53040. I think NLL is correct to reject, but the reason is subtle -- in short, we inferred this closure to be a FnMut closure, but as such, it only has "temporary" mutable access to its captured variables (in this case, v).

That is, it allowed to mutate them, but only during the fn body -- but here we are returning a mutable reference, so we are basically enabling mutation even after the function has returned.

That is not permitted by the signature of FnMut: it would mean that you couldn't call the fn again until you had finished with the return value.

If you use move here, things will build, because then we are FnOnce. You might wonder why the compiler can't infer it -- the answer is that we don't know the lifetime relationships we would need to know until later.

I'm going to close as a duplicate of #53040, in any case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NLL Area: Non-lexical lifetimes (NLL) NLL-complete Working towards the "valid code works" goal T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants