Skip to content

Elided lifetimes in error messages can be incorrect, as well as misleading #87763

Closed
@ssbr

Description

@ssbr

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a08f48d6e07780f4d6a881eddf3459d2

struct S;

trait MyFrom<T> {
    fn from(x: T) -> Self;
}

impl MyFrom<&S> for &S {
    fn from(x: &S) -> &S {
        x
    }
}

The current output is:

error: `impl` item signature doesn't match `trait` item signature
 --> src/lib.rs:8:5
  |
4 |     fn from(x: T) -> Self;
  |     ---------------------- expected `fn(&S) -> &S`
...
8 |     fn from(x: &S) -> &S {
  |     ^^^^^^^^^^^^^^^^^^^^ found `fn(&S) -> &S`
  |
  = note: expected `fn(&S) -> &S`
             found `fn(&S) -> &S`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
 --> src/lib.rs:4:16
  |
4 |     fn from(x: T) -> Self;
  |                ^     ^^^^ consider borrowing this type parameter in the trait
  |                |
  |                consider borrowing this type parameter in the trait

error: aborting due to previous error

Ideally the output should look like:

error: `impl` item signature doesn't match `trait` item signature
 --> src/lib.rs:8:5
  |
4 |     fn from(x: T) -> Self;
  |     ---------------------- expected `fn(&'_1 S) -> &'_2 S`
...
8 |     fn from(x: &S) -> &S {
  |     ^^^^^^^^^^^^^^^^^^^^ found `fn(&'_3 S) -> &'_3 S`
  |
  = note: expected `fn(&'_1 S) -> &'_2 S`
             found `fn(&'_3 S) -> &'_3 S`
    note: the expected lifetimes and found lifetimes are both elided, but differ.
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
 --> src/lib.rs:4:16
  |
4 |     fn from(x: T) -> Self;
  |                ^     ^^^^ consider borrowing this type parameter in the trait
  |                |
  |                consider borrowing this type parameter in the trait

error: aborting due to previous error

Right now, the error message just outputs &S several times, yet there are three different lifetime variables involved here:

  1. '_1, which is the lifetime for the reference that is T
  2. '_2, which is the lifetime for the returned reference that is Self
  3. '_3 the lifetime parameter for the from function in the impl block (which I guess is ~hidden by a for<'_3>)

Because it always elides lifetimes in the error message, the error message produces a false statement of what it expected (it claims to expect fn(&S) -> &S, which is untrue), and presents textually identical "expected" and "found" types.

(Incidentally, the help section about consider borrowing is actually, perhaps accidentally, helpful -- if you move the references to the fn declaration, then they have the same lifetime elision rules as the impl, and everything lines up.)

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