Skip to content

Confusing error message when closures return references based on their arguments #135325

@uellenberg

Description

@uellenberg

Code

struct Val {
    inner: u32
}

fn main() {
    let get_str = |val: &Val| &val.inner;
    
    println!("{}", get_str(&Val { inner: 1 }));
}

Current output

error: lifetime may not live long enough
 --> src/main.rs:6:31
  |
6 |     let get_str = |val: &Val| &val.inner;
  |                         -   - ^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
  |                         |   |
  |                         |   return type of closure is &'2 u32
  |                         let's call the lifetime of this reference `'1`

Desired output

Rationale and extra context

I'm not sure what this specific limitation would be called, but I ran into it recently and thought that the error could give some advice on how to solve it. I'm not sure what the best way to do that is, so I haven't filled out the desired output section.

I was a bit surprised to learn that

struct Val {
    inner: u32
}

fn main() {
    let get_str = |val: &Val| -> &u32 { &val.inner };
    
    println!("{}", get_str(&Val { inner: 1 }));
}

still has the same error (namely, &Val and &u32 are assigned two separate lifetimes), whereas

struct Val {
    inner: u32
}

fn main() {
    let get_str: fn(&Val) -> &u32 = |val: &Val| &val.inner;
    
    println!("{}", get_str(&Val { inner: 1 }));
}

fixes the issue. I'm guessing there's some subtle differences in the way a type is created for a closure (even when the return type explicitly written out) versus specifying the type manually, but I'm honestly not sure. If there's some documentation regarding this, it might be a good idea to mention that in the error message.

Other cases

Rust Version

rustc 1.84.0 (9fc6b4312 2025-01-07)
binary: rustc
commit-hash: 9fc6b43126469e3858e2fe86cafb4f0fd5068869
commit-date: 2025-01-07
host: x86_64-unknown-linux-gnu
release: 1.84.0
LLVM version: 19.1.5

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions