Description
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
, which is the lifetime for the reference that isT
'_2
, which is the lifetime for the returned reference that isSelf
'_3
the lifetime parameter for thefrom
function in the impl block (which I guess is ~hidden by afor<'_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.)