Skip to content

"Lifetime may not live enough"'s suggestion adds a lifetime (incorrectly) to an unrelated impl Trait argument #158954

Description

@ada4a

Code

fn push(vec: &mut Vec<&str>, s: &str, fun: impl Clone) {
    vec.push(s);
}

Current output

Checking tst v0.1.0 (/tmp/tst)
error: lifetime may not live long enough
 --> src/main.rs:4:5
  |
1 | fn push(vec: &mut Vec<&str>, s: &str, fun: impl Clone) {
  |                       -         - let's call the lifetime of this reference `'1`
  |                       |
  |                       let's call the lifetime of this reference `'2`
2 |     vec.push(s);
  |     ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
  |
  = note: requirement occurs because of a mutable reference to `Vec<&str>`
  = note: mutable references are invariant over their type parameter
  = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter
  |
1 | fn push(vec: &mut Vec<&'a str>, s: &'a str, fun: 'a, impl Clone) {
  |                        ++           ++           +++

error: could not compile `tst` (bin "tst") due to 1 previous error

Desired output

Checking tst v0.1.0 (/tmp/tst)
error: lifetime may not live long enough
 --> src/main.rs:4:5
  |
1 | fn push(vec: &mut Vec<&str>, s: &str, fun: impl Clone) {
  |                       -         - let's call the lifetime of this reference `'1`
  |                       |
  |                       let's call the lifetime of this reference `'2`
2 |     vec.push(s);
  |     ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
  |
  = note: requirement occurs because of a mutable reference to `Vec<&str>`
  = note: mutable references are invariant over their type parameter
  = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter
  |
1 | fn push<'a>(vec: &mut Vec<&'a str>, s: &'a str, fun: impl Clone) {
  |        ++++                ++           ++

error: could not compile `tst` (bin "tst") due to 1 previous error

Rationale and extra context

The diagnostic is broken in several ways:

  1. it doesn't actually introduce the lifetime parameter (<'a>)
  2. it adds an 'a, before impl Clone, which is:
    • syntactically invalid
    • unnecessary, since fun isn't even related to the error

Other cases

If I add a reference before the impl Trait:

fn push(vec: &mut Vec<&str>, s: &str, fun: &impl Clone) {
    vec.push(s);
}

the 'a, is added after it:

help: consider introducing a named lifetime parameter
  |
1 | fn push(vec: &mut Vec<&'a str>, s: &'a str, fun: &'a, impl Clone) {
  |                        ++           ++            +++

If I switch to a trait object:

fn push(vec: &mut Vec<&str>, s: &str, fun: &dyn Drop) {
    vec.push(s);
}

(ignore the trait change -- &impl Drop is broken in the same way as &impl Clone)
then the suggestion is actually correct:

help: consider introducing a named lifetime parameter
  |
1 | fn push<'a>(vec: &mut Vec<&'a str>, s: &'a str, fun: &dyn Drop) {
  |        ++++                ++           ++

Rust Version

rustc 1.96.1 (31fca3adb 2026-06-26)
binary: rustc
commit-hash: 31fca3adb283cc9dfd56b49cdee9a96eb9c96ffd
commit-date: 2026-06-26
host: x86_64-unknown-linux-gnu
release: 1.96.1
LLVM version: 22.1.2

Anything else?

This is probably because this:

fn push(vec: &mut Vec<&str>, s: &str, fun: impl Clone) {
    vec.push(s);
}

desugars to this:

fn push<T: Clone>(vec: &mut Vec<&str>, s: &str, fun: T) {
    vec.push(s);
}

and so the suggestion thinks the generics block is already present, and tries to add 'a, to it:

fn push<'a, T: Clone>(vec: &mut Vec<&'a str>, s: &'a str, fun: T) {
//      +++                          ++           ++
    vec.push(s);
}

Metadata

Metadata

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsD-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-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