Skip to content

Surprising lifetime inference with closures #31998

@comex

Description

@comex

The following code fails to compile due to a lifetime error: the intent is for the closure to mutably borrow the variable only until it returns, but somehow the lifetime of the borrow gets inferred to last as long as the variable itself.

fn main() {
    let func = |a| { a; };
  //let func = |a: &mut u32| { a; };
  //let func = |a| { };
    let mut what: u32 = 2;
    loop {
        func(&mut what);
    }
}
a.rs:7:19: 7:23 error: `what` does not live long enough
a.rs:7         func(&mut what);
                         ^~~~
a.rs:2:27: 9:2 note: reference must be valid for the block suffix following statement 0 at 2:26...
a.rs:2     let func = |a| { a; };
a.rs:3   //let func = |a| { };
a.rs:4   //let func = |a: &mut u32| { a; };
a.rs:5     let mut what: u32 = 2;
a.rs:6     loop {
a.rs:7         func(&mut what);
       ...
a.rs:5:27: 9:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 5:26
a.rs:5     let mut what: u32 = 2;
a.rs:6     loop {
a.rs:7         func(&mut what);
a.rs:8     }
a.rs:9 }

Either of the commented alternatives makes compilation succeed. The first, making the lifetime signature (semi-)explicit, makes sense; it's odd that simply removing a useless reference to the variable also works, though.

Anyway, while I don't know how the lifetime inference algorithm works, and in particular I don't know whether improving the situation could impact backwards compatibility, it's surprising to me that it can't figure out a reasonable lifetime in this case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions