Closed
Description
When trying the following code (playground), the result error message is incredibly unhelpful and confusing:
Code sample
#[derive(Clone)]
enum Foo<'a> {
Bar(&'a str),
}
impl<'a> Foo<'a> {
fn bar(&self, other: Foo) -> Foo {
match *self {
Foo::Bar(s) => {
if s == "test" {
other
} else {
self.clone()
}
}
}
}
}
Error message
error[E0308]: mismatched types
--> src/main.rs:11:21
|
11 | other
| ^^^^^ lifetime mismatch
|
= note: expected type `Foo<'_>`
found type `Foo<'_>`
note: the anonymous lifetime #2 defined on the method body at 7:5...
--> src/main.rs:7:5
|
7 | / fn bar(&self, other: Foo) -> Foo {
8 | | match *self {
9 | | Foo::Bar(s) => {
10 | | if s == "test" {
... |
16 | | }
17 | | }
| |_____^
note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 7:5
--> src/main.rs:7:5
|
7 | / fn bar(&self, other: Foo) -> Foo {
8 | | match *self {
9 | | Foo::Bar(s) => {
10 | | if s == "test" {
... |
16 | | }
17 | | }
| |_____^
The expected and found type are both displayed as Foo<'_>
, although I guess this is expected as the two '_
refer to different anonymous lifetimes. But then, it doesn't help that the spans for those two anonymous lifetimes are (visually) identical.
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
estebank commentedon Sep 21, 2017
The presented code is equivalent to
which fails with a similar error, but slightly clearer:
The proper code is
Once you specify a lifetime for
other: Foo<'a>
it works even if the return type is-> Foo {
with the implicit lifetime.We do need to improve the output of this error message. I think this case falls under the same situation as #42703. Once the PR fixing that lands, I'll verify wether it covers this case.
estebank commentedon Oct 5, 2017
Current output for the original code is much improved:
A suggestion to specify a lifetime for the argument is still missing (as the PR handles borrows, not ADTs with borrows), and gives the old diagnostic when the method has the following signature:
That being said, at least in this case it makes a bit more sense, as there's a reference to
'a
and'_
which points in the right direction (it still needs improvement):