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

impl Trait return value infers 'static lifetime #51282

Closed
HMPerson1 opened this issue Jun 1, 2018 · 4 comments
Closed

impl Trait return value infers 'static lifetime #51282

HMPerson1 opened this issue Jun 1, 2018 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.

Comments

@HMPerson1
Copy link
Contributor

This code (playground):

struct Foo {
    v: Vec<u8>
}

impl Foo {
    fn bar(&self) -> impl Iterator<Item=u8> {
        self.v.iter().cloned()
    }
}

fails to compile with:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
 --> src/main.rs:7:16
  |
7 |         self.v.iter().cloned()
  |                ^^^^
  |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
 --> src/main.rs:6:5
  |
6 | /     fn bar(&self) -> impl Iterator {
7 | |         self.v.iter().cloned()
8 | |     }
  | |_____^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:7:9
  |
7 |         self.v.iter().cloned()
  |         ^^^^^^
  = note: but, the lifetime must be valid for the static lifetime...
note: ...so that return value is valid for the call
 --> src/main.rs:6:22
  |
6 |     fn bar(&self) -> impl Iterator<Item=u8> {
  |                      ^^^^^^^^^^^^^^^^^^^^^^

Replacing impl Iterator with an explicit type works:

fn bar(&self) -> std::iter::Cloned<std::slice::Iter<u8>> {
    self.v.iter().cloned()
}

Explicitly bounding the output lifetime also works:

fn bar<'a>(&'a self) -> impl Iterator<Item=u8> + 'a {
    self.v.iter().cloned()
}
@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch. labels Jun 1, 2018
@estebank
Copy link
Contributor

estebank commented Jun 1, 2018

I don't know what the implications are of starting to infer 'self instead of 'static, but we could definitely improve the error message to help you fix the code.

The following code also works:

struct Foo {
    v: Vec<u8>
}

impl Foo {
    fn bar1(&self) -> impl Iterator<Item=u8> + '_ {
        self.v.iter().cloned()
    }

    fn bar2(&self) -> std::iter::Cloned<std::slice::Iter<u8>> {
        self.v.iter().cloned()
    }

    fn bar3<'a>(&'a self) -> impl Iterator<Item=u8> + 'a {
        self.v.iter().cloned()
    }
}

fn main() {}

@nikomatsakis what do you think would break by modifying the behavior to infer impl Trait + '_? The thing that was worrying me mostly (impl Trait + '_ + 'a), works.

@HMPerson1
Copy link
Contributor Author

Oh, I didn't realize that lifetimes had to be brought into scope first. 😅

So then this works:

fn bar(&self) -> impl Iterator<Item=u8> + '_ {
    self.v.iter().cloned()
}

@estebank
Copy link
Contributor

estebank commented Jun 8, 2018

cc #43719, #38615

bors added a commit that referenced this issue Jun 28, 2018
Suggestion for 'static impl Trait return

When encountering a named or anonymous sup requirement (for example,
`&'a self`) and a `'static` impl Trait return type, suggest adding the
`'_` lifetime constraing to the return type.

Fix #43719, #51282.

```
error: cannot infer an appropriate lifetime
  --> $DIR/static-return-lifetime-infered.rs:17:16
   |
LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
   |                                   ----------------------- this return type evaluates to the `'static` lifetime...
LL |         self.x.iter().map(|a| a.0)
   |         ------ ^^^^
   |         |
   |         ...but this borrow...
   |
note: ...can't outlive the anonymous lifetime #1 defined on the method body at 16:5
  --> $DIR/static-return-lifetime-infered.rs:16:5
   |
LL | /     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
LL | |         self.x.iter().map(|a| a.0)
LL | |     }
   | |_____^
help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 16:5
   |
LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
@estebank
Copy link
Contributor

Current output:

error: cannot infer an appropriate lifetime
 --> src/main.rs:7:16
  |
6 |     fn bar1(&self) -> impl Iterator<Item=u8> {
  |                       ---------------------- this return type evaluates to the `'static` lifetime...
7 |         self.v.iter().cloned()
  |         ------ ^^^^
  |         |
  |         ...but this borrow...
  |
note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5
 --> src/main.rs:6:5
  |
6 | /     fn bar1(&self) -> impl Iterator<Item=u8> {
7 | |         self.v.iter().cloned()
8 | |     }
  | |_____^
help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5
  |
6 |     fn bar1(&self) -> impl Iterator<Item=u8> + '_ {
  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^

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-impl-trait Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
Projects
None yet
Development

No branches or pull requests

2 participants