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

Comments

Projects
None yet
2 participants
@HMPerson1
Copy link

HMPerson1 commented Jun 1, 2018

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

This comment has been minimized.

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

This comment has been minimized.

Copy link
Author

HMPerson1 commented Jun 1, 2018

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

This comment has been minimized.

Copy link
Contributor

estebank commented Jun 8, 2018

bors added a commit that referenced this issue Jun 28, 2018

Auto merge of #51444 - estebank:impl-static, r=nikomatsakis
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

This comment has been minimized.

Copy link
Contributor

estebank commented Jul 15, 2018

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> + '_ {
  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^

@estebank estebank closed this Jul 15, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment