Skip to content

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

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.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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