[SOLVED] Trait with lifetime parameter and compiler message I don't understand


#1

Hi there.

Could someone please explain, what’s wrong with this code:

trait Foo<'a> {
}

struct FooImpl<'a> {
    s: &'a [u32],
}

impl<'a> Foo<'a> for FooImpl<'a> {
}

fn foo<'a>(s: &'a [u32]) -> Box<Foo<'a>> {
    Box::new(FooImpl { s: s })
}

Code seems to be valid to me, and I don’t understand the compiler message:

error: cannot infer an appropriate lifetime due to conflicting requirements [E0495]
  --> <anon>:12:14
   |>
12 |>     Box::new(FooImpl { s: s })
   |>              ^^^^^^^
note: first, the lifetime cannot outlive the lifetime 'a as defined on the block at 11:41...
  --> <anon>:11:42
   |>
11 |> fn foo<'a>(s: &'a [u32]) -> Box<Foo<'a>> {
   |>                                          ^
note: ...so that reference does not outlive borrowed content
  --> <anon>:12:27
   |>
12 |>     Box::new(FooImpl { s: s })
   |>                           ^
note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `FooImpl<'_>` will meet its required lifetime bounds
  --> <anon>:12:5
   |>
12 |>     Box::new(FooImpl { s: s })
   |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

#2

Only because you haven’t taken lifetime elision into account. Here’s what your code actually says:

fn foo<'a>(s: &'a [u32]) -> Box<Foo<'a> + 'static> {
    Box::new(FooImpl { s: s })
}

For every trait object, there must be a concrete type that implements said trait. That concrete type might contain lifetimes. Thus, every trait object needs to have a known minimum lifetime which all implementing types must adhere to. Because Box is owned and can survive indefinitely, it’s default minimum lifetime is 'static. This is written Box<Trait + 'static>.

Hence the error.

The solution is to override this default:

fn foo<'a>(s: &'a [u32]) -> Box<Foo<'a> + 'a> {
    Box::new(FooImpl { s: s })
}

#3

Thank you!