Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle ADTs with implicit lifetime params resulting a lifetime mismatch in fn definition #40990

Closed
Tracked by #42516
TomasTomecek opened this issue Apr 1, 2017 · 4 comments · Fixed by #124682
Closed
Tracked by #42516
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. C-enhancement Category: An issue proposing an enhancement or a PR with one. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@TomasTomecek
Copy link

I have this function:

use git2::Reference;
fn resolve_symbolic_reference(&self, reference: Option<Reference>) -> Option<Reference> {
    return reference;
    // here's more logic, this is just shortened for clarity
}

Here's the source of the struct.

And I get this from compiler:

error[E0308]: mismatched types
  --> src/backend.rs:71:16
   |
71 |         return reference;
   |                ^^^^^^^^^ lifetime mismatch
   |
   = note: expected type `std::option::Option<git2::Reference<'_>>`
              found type `std::option::Option<git2::Reference<'_>>`
note: the anonymous lifetime #2 defined on the body at 70:92...
  --> src/backend.rs:70:93
   |
70 |     fn resolve_symbolic_reference(&self, reference: Option<Reference>) -> Option<Reference> {
   |                                                                                             ^
note: ...does not necessarily outlive the anonymous lifetime #1 defined on the body at 70:92
  --> src/backend.rs:70:93
   |
70 |     fn resolve_symbolic_reference(&self, reference: Option<Reference>) -> Option<Reference> {
   |                                                                                             ^

error: aborting due to previous error

First of all: I don't understand what's wrong with my code: isn't the lifetime of the function argument problem of the caller of my function?
Second: the compiler's error message is not helpful, especially:

   = note: expected type `std::option::Option<git2::Reference<'_>>`
              found type `std::option::Option<git2::Reference<'_>>`

I run rust unstable installed via rustup:

$ rustc 1.17.0-nightly (0aeb9c129 2017-03-15)
binary: rustc
commit-hash: 0aeb9c12979e6da753701a798d04105b6b1a8c28
commit-date: 2017-03-15
host: x86_64-unknown-linux-gnu
release: 1.17.0-nightly
LLVM version: 3.9

I have also reported this to the library's upstream.

@TomasTomecek
Copy link
Author

So the original issue is resolved: I still think that it would be very helpful if compiler provided precise info about lifetimes.

@jdm jdm added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related labels Apr 2, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 26, 2017
@estebank
Copy link
Contributor

estebank commented Oct 11, 2019

The current output:

error[E0623]: lifetime mismatch
 --> src/lib.rs:8:12
  |
7 | fn resolve_symbolic_reference(&self, reference: Option<Reference>) -> Option<Reference> {
  |                                                        ---------      -----------------
  |                                                        |
  |                                                        this parameter and the return type are declared with different lifetimes...
8 |     return reference;
  |            ^^^^^^^^^ ...but data from `reference` is returned here

It should suggest adding a common lifetime argument to both References.

With nll enabled:

error: lifetime may not live long enough
  --> src/lib.rs:10:12
   |
9  | fn resolve_symbolic_reference(&self, reference: Option<Reference>) -> Option<Reference> {
   |                               -      --------- has type `std::option::Option<Reference<'1>>`
   |                               |
   |                               let's call the lifetime of this reference `'2`
10 |     return reference;
   |            ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

@estebank estebank added A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. D-papercut Diagnostics: An error or lint that needs small tweaks. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 11, 2019
@estebank estebank changed the title lifetime mismatch: compiler's error message is not helpful Handle ADTs with implicit lifetime params resulting a lifetime mismatch in fn definition Oct 11, 2019
@estebank estebank added the D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. label Oct 11, 2019
@rylev
Copy link
Member

rylev commented Dec 9, 2020

Triage: this still returns the same error above (the one not labeled as nll).

This issue also stems from the fact that by default, borrowed return types in methods get the same lifetime as &self which is distinct from the lifetime of arguments. Adding a note to this effect can also help. Something like:

error[E0623]: lifetime mismatch
 --> src/lib.rs:5:16
  |
4 |     fn resolve_symbolic_reference(&self, reference: Option<Reference>) -> Option<Reference> {
  |                                                            ---------      -----------------
  |                                                            |
  |                                                            this parameter and the return type are declared with different lifetimes...
5 |         return reference;
  |                ^^^^^^^^^ ...but data from `reference` is returned here
  = note: by default the lifetime of the return type and `&self` are the same while the method arguments have a different lifetime.
  = note: consider giving `&self`, the arguments, and the return type explicit lifetime annotations.   

@estebank
Copy link
Contributor

estebank commented Aug 3, 2023

We now emit the nll output. It should suggest &'a self and Reference<'a>.

estebank added a commit to estebank/rust that referenced this issue May 3, 2024
…d lifetimes

```
error: lifetime may not live long enough
  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:5
   |
LL | fn foo(mut x: Ref, y: Ref) {
   |        -----       - has type `Ref<'_, '1>`
   |        |
   |        has type `Ref<'_, '2>`
LL |     x.b = y.b;
   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
   |
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'a, 'a>, y: Ref<'a, 'a>) {
   |       ++++           ++++++++        ++++++++
```

As can be seen above, it currently doesn't try to compare the `ty::Ty` lifetimes that diverged vs the `hir::Ty` to correctly suggest the following

```
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'_, 'a>, y: Ref<'_, 'a>) {
   |       ++++           ++++++++        ++++++++
```

but I believe this to still be an improvement over the status quo.

CC rust-lang#40990.
estebank added a commit to estebank/rust that referenced this issue May 5, 2024
…d lifetimes

```
error: lifetime may not live long enough
  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:5
   |
LL | fn foo(mut x: Ref, y: Ref) {
   |        -----       - has type `Ref<'_, '1>`
   |        |
   |        has type `Ref<'_, '2>`
LL |     x.b = y.b;
   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
   |
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'a, 'a>, y: Ref<'a, 'a>) {
   |       ++++           ++++++++        ++++++++
```

As can be seen above, it currently doesn't try to compare the `ty::Ty` lifetimes that diverged vs the `hir::Ty` to correctly suggest the following

```
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'_, 'a>, y: Ref<'_, 'a>) {
   |       ++++           ++++++++        ++++++++
```

but I believe this to still be an improvement over the status quo.

CC rust-lang#40990.
estebank added a commit to estebank/rust that referenced this issue May 17, 2024
…d lifetimes

```
error: lifetime may not live long enough
  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:5
   |
LL | fn foo(mut x: Ref, y: Ref) {
   |        -----       - has type `Ref<'_, '1>`
   |        |
   |        has type `Ref<'_, '2>`
LL |     x.b = y.b;
   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
   |
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'a, 'a>, y: Ref<'a, 'a>) {
   |       ++++           ++++++++        ++++++++
```

As can be seen above, it currently doesn't try to compare the `ty::Ty` lifetimes that diverged vs the `hir::Ty` to correctly suggest the following

```
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'_, 'a>, y: Ref<'_, 'a>) {
   |       ++++           ++++++++        ++++++++
```

but I believe this to still be an improvement over the status quo.

CC rust-lang#40990.
@bors bors closed this as completed in 29c603c May 20, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue May 20, 2024
Rollup merge of rust-lang#124682 - estebank:issue-40990, r=pnkfelix

Suggest setting lifetime in borrowck error involving types with elided lifetimes

```
error: lifetime may not live long enough
  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:5
   |
LL | fn foo(mut x: Ref, y: Ref) {
   |        -----       - has type `Ref<'_, '1>`
   |        |
   |        has type `Ref<'_, '2>`
LL |     x.b = y.b;
   |     ^^^^^^^^^ assignment requires that `'1` must outlive `'2`
   |
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'a, 'a>, y: Ref<'a, 'a>) {
   |       ++++           ++++++++        ++++++++
```

As can be seen above, it currently doesn't try to compare the `ty::Ty` lifetimes that diverged vs the `hir::Ty` to correctly suggest the following

```
help: consider introducing a named lifetime parameter
   |
LL | fn foo<'a>(mut x: Ref<'_, 'a>, y: Ref<'_, 'a>) {
   |       ++++           ++++++++        ++++++++
```

but I believe this to still be an improvement over the status quo.

Fix rust-lang#40990.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. C-enhancement Category: An issue proposing an enhancement or a PR with one. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants