Why explicit lifetime is needed in the following code?

trait Container {
    type Value;
    fn first(&mut self) -> &mut Self::Value;
}
trait Wrapper {
    type ConcreteContainer: Container;
    fn container(&mut self) -> &mut Self::ConcreteContainer;
}
impl<V, C, W> Container for W 
where
    C: Container<Value = V>,
    W: Wrapper<ConcreteContainer = C>
{
    type Value = V;
    fn first(&mut self) -> &mut Self::Value {
        self.container().first() // Here is error: the parameter type `C` may not live long enough
    }
}

It seems like

  • first (in the trait) returns a reference to Value that lives not less than self (Container)
  • container returns a reference to ConcreteContainer that lives not less than self (Wrapper)

So does self.container().first() returns a reference to Value that lives not less than self (Container)?

But following works:

trait Container<'a> {
    type Value;
    fn first(&'a mut self) -> &'a mut Self::Value;
}
trait Wrapper {
    type ConcreteContainer: for <'a> Container<'a>;
    fn container(&mut self) -> &mut Self::ConcreteContainer;
}
impl<'a, V, C, W> Container<'a> for W 
where
    C: 'a + Container<'a, Value = V>,
    W: Wrapper<ConcreteContainer = C>
{
    type Value = V;
    fn first(&'a mut self) -> &'a mut Self::Value {
        self.container().first()
    }
}

It looks like a case of this compiler bug: Naming an associated type can cause a compile failure · Issue #74007 · rust-lang/rust · GitHub

You can work around this by changing how you refer to the associated types C and V:

trait Container {
    type Value;
    fn first(&mut self) -> &mut Self::Value;
}
trait Wrapper {
    type ConcreteContainer: Container;
    fn container(&mut self) -> &mut Self::ConcreteContainer;
}
impl<W> Container for W 
where
    W: Wrapper
{
    type Value = <W::ConcreteContainer as Container>::Value;
    fn first(&mut self) -> &mut Self::Value {
        self.container().first()
    }
}
3 Likes

Thanks! You've discovered a new syntax for me)