Skip to content

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

@ssbr

Description

@ssbr
Contributor

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

added
A-diagnosticsArea: Messages for errors, warnings, and lints
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Aug 4, 2021
added a commit that references this issue on Aug 4, 2021
added a commit that references this issue on Oct 1, 2021
82348ef
added a commit that references this issue on Oct 22, 2021
0cc8b39
added a commit that references this issue on Oct 22, 2021
98ed554
added a commit that references this issue on Oct 23, 2021
d64b3a7
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

      Participants

      @ssbr

      Issue actions

        Elided lifetimes in error messages can be incorrect, as well as misleading · Issue #87763 · rust-lang/rust