Skip to content

associated types in generics cause lifetime invariance #115799

Open
@tamird

Description

@tamird

playground

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions