Skip to content

NLL regresses diagnostic for impl-trait/static-return-lifetime-infered.rs #53771

Closed
@pnkfelix

Description

@pnkfelix

Consider this code from static-return-lifetime-infered.rs (play):

// #![feature(nll)]

struct A {
    x: [(u32, u32); 10]
}

impl A {
    fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
        self.x.iter().map(|a| a.0)
    }
    //~^^ ERROR cannot infer an appropriate lifetime
    fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
        self.x.iter().map(|a| a.0)
    }
    //~^^ ERROR cannot infer an appropriate lifetime
}

fn main() {}

Part of the diagnostic info you get is this useful help message:

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 8:5
  |
8 |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
  |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Unfortunately, under #![feature(nll)], we fail to produce that help diagnostic (play):

error: unsatisfied lifetime constraints
 --> src/main.rs:9:9
  |
8 |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
  |                         - let's call the lifetime of this reference `'1`
9 |         self.x.iter().map(|a| a.0)
  |         ^^^^^^^^^^^^^ requires that `'1` must outlive `'static`

error: unsatisfied lifetime constraints
  --> src/main.rs:13:9
   |
12 |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
   |                    -- lifetime `'a` defined here
13 |         self.x.iter().map(|a| a.0)
   |         ^^^^^^^^^^^^^ requires that `'a` must outlive `'static`

error: aborting due to 2 previous errors

"Luckily", this does not need to be a high priority issue for us to resolve, because in the special "migration" mode for NLL (which you can observe today by opting into the 2018 edition), we do produce the help message (play):

error: cannot infer an appropriate lifetime
 --> src/main.rs:9:16
  |
8 |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
  |                                   ----------------------- this return type evaluates to the `'static` lifetime...
9 |         self.x.iter().map(|a| a.0)
  |         ------ ^^^^
  |         |
  |         ...but this borrow...
  |
note: ...can't outlive the anonymous lifetime #1 defined on the method body at 8:5
 --> src/main.rs:8:5
  |
8 | /     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
9 | |         self.x.iter().map(|a| a.0)
10| |     }
  | |_____^
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 8:5
  |
8 |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
  |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: cannot infer an appropriate lifetime
  --> src/main.rs:13:16
   |
12 |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
   |                                     ----------------------- this return type evaluates to the `'static` lifetime...
13 |         self.x.iter().map(|a| a.0)
   |         ------ ^^^^
   |         |
   |         ...but this borrow...
   |
note: ...can't outlive the lifetime 'a as defined on the method body at 12:20
  --> src/main.rs:12:20
   |
12 |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
   |                    ^^
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 12:20
   |
12 |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Metadata

Metadata

Assignees

Labels

A-NLLArea: Non-lexical lifetimes (NLL)NLL-diagnosticsWorking towards the "diagnostic parity" goal

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions