Type alias doesn't work with `dyn Trait`

I encountered a lifetime issue when using type alias with dyn Trait. Here's the simplified code:

trait Foo {
    fn work(&self, arg: &impl Bar);
}
trait Bar {}
type DynBar = dyn Bar;

impl<F> Foo for F
where
 // F: Fn(&dyn Bar),
    F: Fn(&DynBar),
{
    fn work(&self, arg: &impl Bar) {
        self(arg)
    }
}

The compiler say:

error[E0310]: the parameter type `impl Bar` may not live long enough
  --> src\main.rs:14:14
   |
14 |         self(arg)
   |              ^^^
   |              |
   |              the parameter type `impl Bar` must be valid for the static lifetime...
   |              ...so that the type `impl Bar` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
13 |     fn work(&self, arg: &impl Bar + 'static) {
   |                                   +++++++++

What's going on? Shouldn't type aliases be just simple substitutions? If the type alias is not used, it will compile fine.

type DynBar = dyn Bar is a type definition for type DynBar = dyn Bar + 'static with the 'static lifetime being elided:

3 Likes

So for my use case the correct way to write it is:

type DynBar<'a> = dyn Bar + 'a;

impl<F> Foo for F
where
    F: for<'a> Fn(&DynBar<'a>),
{
    fn work(&self, arg: &impl Bar) {
        self(arg)
    }
}

The resources you provided are very helpful to me, thanks.

1 Like

Yes. You can simplify the type signature of the Foo impl a bit if you prefer:

impl<F> Foo for F
where
    F: Fn(&DynBar<'_>),
1 Like

You might want to think through exactly how you expect everything to be used. Both of these:

impl<F> Foo for F
where
    F: for<'a> Fn(&DynBar<'a>),
impl<F> Foo for F
where
    F: Fn(&DynBar<'_>),

Say "in order to implement Foo, you have accept every combination of lifetimes in &DynBar<'_>:"

F: for<'r, 'a> Fn(&'r DynBar<'a>)

But if you have a function with a signature like this:

fn does_not_use_alias(_: &dyn Bar) {}

It only implements for<'b> Fn(&'b DynBar<'b>) due to how the elision works (note how the lifetimes are the same).


Incidentally, part of why I wrote such a lengthy section on lifetimes is that the reference is inaccurate on this topic. (The basic guidelines are enough for most use cases.)

2 Likes