Open
Description
trait WithAssoc {
type Assoc;
}
struct ImplsAssoc<'a> {
phantom: core::marker::PhantomData<&'a ()>,
}
impl WithAssoc for ImplsAssoc<'_> {
type Assoc = ();
}
struct Holder<W: WithAssoc> {
foo: W,
bar: W::Assoc,
}
struct CovariantHolder<W: WithAssoc<Assoc = Assoc>, Assoc = <W as WithAssoc>::Assoc> {
foo: W,
bar: Assoc,
}
// This doesn't compile.
fn invariant<'a: 'b, 'b>(x: Holder<ImplsAssoc<'a>>) -> Holder<ImplsAssoc<'b>> {
x
}
// This compiles.
fn covariant<'a: 'b, 'b>(x: CovariantHolder<ImplsAssoc<'a>>) -> CovariantHolder<ImplsAssoc<'b>> {
x
}
24 | fn invariant<'a: 'b, 'b>(x: Holder<ImplsAssoc<'a>>) -> Holder<ImplsAssoc<'b>> {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
25 | x
| ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of the type `Holder<ImplsAssoc<'_>>`, which makes the generic argument `ImplsAssoc<'_>` invariant
= note: the struct `Holder<W>` is invariant over the parameter `W`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
It's not clear to me why Holder
and CovariantHolder
are any different. It's not possible construct a CovariantHolder<T, S>
where S
is anything other than <T as WithAssoc>::Assoc
. Why does the compiler treat them differently?