Mismatched lifetime in trait function declaration is not detected

db5408f
Opened by Mike Hommey at 2023-08-03 16:51:46

Consider the following code:

pub trait FromStr<'a>: Sized {
    type Err;
    fn from_str(s: &'a str) -> Result<Self, Self::Err>;
}

struct Foo<'a>(&'a str);

impl<'a> FromStr<'a> for Foo<'a> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Foo(s))
    }
}

The compiler errors out failing to infer an appropriate lifetime:


error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:11:12
   |
11 |         Ok(Foo(s))
   |            ^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 10:5...
  --> src/main.rs:10:5
   |
10 | /     fn from_str(s: &str) -> Result<Self, Self::Err> {
11 | |         Ok(Foo(s))
12 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:11:16
   |
11 |         Ok(Foo(s))
   |                ^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 8:1...
  --> src/main.rs:8:1
   |
8  | impl<'a> FromStr<'a> for Foo<'a> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...so that the expression is assignable:
           expected std::result::Result<Foo<'a>, _>
              found std::result::Result<Foo<'_>, _>

But the most immediate error is that the declaration of from_str doesn't match the trait definition, missing the lifetime bound on &str to match the lifetime associated with the trait.

  1. Current output:

    error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
      --> src/lib.rs:11:12
       |
    11 |         Ok(Foo(s))
       |            ^^^
       |
    note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 10:5...
      --> src/lib.rs:10:5
       |
    10 | /     fn from_str(s: &str) -> Result<Self, Self::Err> {
    11 | |         Ok(Foo(s))
    12 | |     }
       | |_____^
    note: ...so that reference does not outlive borrowed content
      --> src/lib.rs:11:16
       |
    11 |         Ok(Foo(s))
       |                ^
    note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 8:6...
      --> src/lib.rs:8:6
       |
    8  | impl<'a> FromStr<'a> for Foo<'a> {
       |      ^^
    note: ...so that the expression is assignable
      --> src/lib.rs:11:9
       |
    11 |         Ok(Foo(s))
       |         ^^^^^^^^^^
       = note: expected  `std::result::Result<Foo<'a>, _>`
                  found  `std::result::Result<Foo<'_>, _>`
    

    Output with nll enabled:

    error: lifetime may not live long enough
      --> src/lib.rs:12:9
       |
    9  | impl<'a> FromStr<'a> for Foo<'a> {
       |      -- lifetime `'a` defined here
    10 |     type Err = ();
    11 |     fn from_str(s: &str) -> Result<Self, Self::Err> {
       |                    - let's call the lifetime of this reference `'1`
    12 |         Ok(Foo(s))
       |         ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
    

    Esteban Kuber at 2020-02-12 20:28:12

  2. Current output is the nll one above. Ideally we'd suggest using &'a str instead of &str, but the error already gives enough information to deal with the problem.

    Esteban Kuber at 2023-08-03 16:51:18