Misleading "Lifetime Must Outlive x" Diagnostic
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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