Skip to content

diagnostics for lifetime issues sometimes point to code unrelated to the issue #102231

@lovasoa

Description

@lovasoa

Given the following code:

struct X<'a>(&'a ());

impl<'a> X<'a> {
     fn get_self(&mut self) -> &mut X<'a> {
        self
    }   
}

fn f<'a>(_y1: &'a mut X<'a>, _y2: &'a mut X<'a>) {}

fn g<'a, 'b>(x1: &mut X<'a>, x2: &mut X<'b>) {
    let y1 = x1.get_self();
    let y2 = x2.get_self();
    // ... Potentially hundreds of lines of code here...
    f(y1, y2);
    // ... Potentially hundreds of lines of code here...
}

(Playground link)

The current output is:

error[[E0621]](https://doc.rust-lang.org/stable/error-index.html#E0621): explicit lifetime required in the type of `x1`
  --> src/lib.rs:12:14
   |
11 | fn g<'a, 'b>(x1: &mut X<'a>, x2: &mut X<'b>) {
   |                  ---------- help: add explicit lifetime `'a` to the type of `x1`: `&'a mut X<'a>`
12 |     let y1 = x1.get_self();
   |              ^^^^^^^^^^^^^ lifetime `'a` required

error: lifetime may not live long enough
  --> src/lib.rs:12:14
   |
11 | fn g<'a, 'b>(x1: &mut X<'a>, x2: &mut X<'b>) {
   |      --  -- lifetime `'b` defined here
   |      |
   |      lifetime `'a` defined here
12 |     let y1 = x1.get_self();
   |              ^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
   |
   = help: consider adding the following bound: `'a: 'b`
   = note: requirement occurs because of a mutable reference to `X<'_>`
   = note: mutable references are invariant over their type parameter
   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: lifetime may not live long enough
  --> src/lib.rs:12:14
   |
11 | fn g<'a, 'b>(x1: &mut X<'a>, x2: &mut X<'b>) {
   |      --  -- lifetime `'b` defined here
   |      |
   |      lifetime `'a` defined here
12 |     let y1 = x1.get_self();
   |              ^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
   |
   = help: consider adding the following bound: `'b: 'a`
   = note: requirement occurs because of a mutable reference to `X<'_>`
   = note: mutable references are invariant over their type parameter
   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error[[E0621]](https://doc.rust-lang.org/stable/error-index.html#E0621): explicit lifetime required in the type of `x2`
  --> src/lib.rs:13:14
   |
11 | fn g<'a, 'b>(x1: &mut X<'a>, x2: &mut X<'b>) {
   |                                  ---------- help: add explicit lifetime `'a` to the type of `x2`: `&'a mut X<'b>`
12 |     let y1 = x1.get_self();
13 |     let y2 = x2.get_self();
   |              ^^^^^^^^^^^^^ lifetime `'a` required

help: `'a` and `'b` must be the same: replace one with the other

For more information about this error, try `rustc --explain E0621`.
error: could not compile `playground` due to 4 previous errors

Ideally the output should look like:

error: lifetime may not live long enough
  --> src/lib.rs:15:4
15 |     f(y1, y2);
   |           ^^ argument requires that `'b` must outlive `'a`
   |
   = help: consider adding the following bound: `'b: 'a`
   = help: y2 has type &mut X<'b> but function `f` expected &mut X<'a>

Context

I was working on a code refactoring involving many lifetime annotations (sunng87/handlebars-rust#532) for my work on an efficient template cache in SQLPage, and this issue blocked me for way too long before I realized the compiler was pointing me in the wrong direction.

In the code snippet above, the first two lines in g are no-ops. The real issue is trying to call the function f with arguments that don't match its lifetime requirements.

But the compiler says something that made it very hard for me to figure out where the problem was :

x1.get_self();
^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`

This sentence just seems wrong.

  • First there doesn't seem to be any "argument" in the highlighted code. It looks like the compiler is referring to x1, as an "argument" to get_self, but it's not obvious.
  • Second, get_self doesn't require that 'a must outlive 'b. get_self doesn't even see more than one lifetime. The requirement happens later, when f is called, but the compiler does not point to it, and the programmer has to find it himself, buried in potentially hundreds of lines of unrelated code.

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