fn param_env_with_gat_bounds<'tcx>(
    tcx: TyCtxt<'tcx>,
    impl_ty: AssocItem,
    impl_trait_ref: TraitRef<'tcx>,
) -> ParamEnv<'tcx>
Expand description

Install projection predicates that allow GATs to project to their own definition types. This is not allowed in general in cases of default associated types in trait definitions, or when specialization is involved, but is needed when checking these definition types actually satisfy the trait bounds of the GAT.

§How it works

impl<A, B> Foo<u32> for (A, B) {
    type Bar<C> = Wrapper<A, B, C>
}
  • impl_trait_ref would be <(A, B) as Foo<u32>>
  • normalize_impl_ty_args would be [A, B, ^0.0] (^0.0 here is the bound var with db 0 and index 0)
  • normalize_impl_ty would be Wrapper<A, B, ^0.0>
  • rebased_args would be [(A, B), u32, ^0.0], combining the args from the trait with the generic associated type parameters (as bound vars).

A note regarding the use of bound vars here: Imagine as an example

trait Family {
    type Member<C: Eq>;
}

impl Family for VecFamily {
    type Member<C: Eq> = i32;
}

Here, we would generate

forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }

when we really would like to generate

forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }

But, this is probably fine, because although the first clause can be used with types C that do not implement Eq, for it to cause some kind of problem, there would have to be a VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in the trait (notably, that X: Eq and T: Family).