rustc_trait_selection::traits::dyn_compatibility

Function contains_illegal_self_type_reference

Source
fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
    tcx: TyCtxt<'tcx>,
    trait_def_id: DefId,
    value: T,
    allow_self_projections: AllowSelfProjections,
) -> bool
Expand description

This is somewhat subtle. In general, we want to forbid references to Self in the argument and return types, since the value of Self is erased. However, there is one exception: it is ok to reference Self in order to access an associated type of the current trait, since we retain the value of those associated types in the object type itself.

trait SuperTrait {
    type X;
}

trait Trait : SuperTrait {
    type Y;
    fn foo(&self, x: Self) // bad
    fn foo(&self) -> Self // bad
    fn foo(&self) -> Option<Self> // bad
    fn foo(&self) -> Self::Y // OK, desugars to next example
    fn foo(&self) -> <Self as Trait>::Y // OK
    fn foo(&self) -> Self::X // OK, desugars to next example
    fn foo(&self) -> <Self as SuperTrait>::X // OK
}

However, it is not as simple as allowing Self in a projected type, because there are illegal ways to use Self as well:

trait Trait : SuperTrait {
    ...
    fn foo(&self) -> <Self as SomeOtherTrait>::X;
}

Here we will not have the type of X recorded in the object type, and we cannot resolve Self as SomeOtherTrait without knowing what Self is.