rust-lang / rust-lang/rust

Misleading "Lifetime Must Outlive x" Diagnostic

Open
#147,564 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics A-lifetimes T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
fn filter_guest_list_and_add_bob<'bob, 'guests: 'bob>(
    guests: Vec<&'guests str>,
    bob: &'bob str,
) -> Vec<&'guests str> {
    let mut filtered: Vec<&'guests str> = Vec::new();
    for g in guests {
        if g.starts_with("vip") {
            filtered.push(g);
        }
    }
    filtered.push(bob);
    filtered
}
Current output
error: lifetime may not live long enough
 --> src/main.rs:5:23
  |
1 | fn filter_guest_list_and_add_bob<'bob, 'guests: 'bob>(
  |                                  ----  ------- lifetime `'guests` defined here
  |                                  |
  |                                  lifetime `'bob` defined here
...
5 |     let mut filtered: Vec<&'guests str> = Vec::new();
  |                       ^^^^^^^^^^^^^^^^^ type annotation requires that `'bob` must outlive `'guests`
  |
  = help: consider adding the following bound: `'bob: 'guests`

error: aborting due to 1 previous error
Desired output
error: lifetime may not live long enough
  --> src/main.rs:11:23
   |
 1 | fn filter_guest_list_and_add_bob<'bob, 'guests: 'bob>(
   |                                  ----  ------- lifetime `'guests` outlives `'bob`
   |                                  |
   |                                  lifetime `'bob` defined here
...
11 |     filtered.push(bob);
   |                   ^^^ `filtered` requires values that live at least as long as `'guests` but `'guests` outlive `'bob`
   |
Rationale and extra context

If I mix incompatible lifetimes at the use of a function/method I expect to have that location highlighted in the diagnostic so I can see whether the definition or use is wrong. This is what "normal type errors" already do:

For example if I swap the lifetimes & strings for types u32 & u16 I get a much more intuitive error highlighting which line caused filtered to be inferred as u32 and then a subsequent type mismatch at the site of the second push:

fn filter_guest_list_and_add_bob(guests: Vec<u32>, bob: u16) -> Vec<u32> {
    let mut filtered = Vec::new();
    for g in guests {
        if g < 100 {
            filtered.push(g);
        }
    }
    filtered.push(bob);
    filtered
}

More intuitive error:

error[E0308]: mismatched types
    --> src/main.rs:8:19
     |
   5 |             filtered.push(g);
     |             --------      - this argument has type `u32`...
     |             |
     |             ... which causes `filtered` to have type `Vec<u32>`
...
   8 |     filtered.push(bob);
     |              ---- ^^^ expected `u32`, found `u16`
     |              |
     |              arguments to this method are incorrect
     |
note: method defined here
    --> /Users/philogy/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:2521:12
     |
2521 |     pub fn push(&mut self, value: T) {
     |            ^^^^
help: you can convert a `u16` to a `u32`
     |
   8 |     filtered.push(bob.into());
     |                      +++++++

error: aborting due to 1 previous error
Other cases

Rust Version
rustc 1.90.0 (1159e78c4 2025-09-14)
binary: rustc
commit-hash: 1159e78c4747b02ef996e55082b704c09b970588
commit-date: 2025-09-14
host: aarch64-apple-darwin
release: 1.90.0
LLVM version: 20.1.8
Anything else?

Even more confusing I get the same error but at the return expression if I don't add an explicit type:

fn filter_guest_list_and_add_bob<'bob, 'guests: 'bob>(
    guests: Vec<&'guests str>,
    bob: &'bob str,
) -> Vec<&'guests str> {
    let mut filtered = Vec::new();
    for g in guests {
        if g.starts_with("vip") {
            filtered.push(g);
        }
    }
    filtered.push(bob);
    filtered
}

Error:

error: lifetime may not live long enough
  --> src/main.rs:12:5
   |
 1 | fn filter_guest_list_and_add_bob<'bob, 'guests: 'bob>(
   |                                  ----  ------- lifetime `'guests` defined here
   |                                  |
   |                                  lifetime `'bob` defined here
...
12 |     filtered
   |     ^^^^^^^^ function was supposed to return data with lifetime `'guests` but it is returning data with lifetime `'bob`
   |
   = help: consider adding the following bound: `'bob: 'guests`

error: aborting due to 1 previous error

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the supplied examples with the reported rustc version and compare the diagnostics with and without the explicit vector type. Trace the compiler's lifetime-diagnostic path, then verify that the conflicting push or return is highlighted and that the labels and wording explain the actual outlives relationship.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.