Note [Type application substitution]
In `tc_inst_forall_arg`, suppose we are checking a visible type application `f @hs_ty`, where `f :: forall (a :: k). body`. We will: * Compute `ty <- tcHsTypeApp hs_ty k` * Then substitute `a :-> ty` in `body`. Now, you might worry that `a` might not have the same kind as `ty`, so that the substitution isn't kind-preserving. How can that happen? The kinds will definitely be the same after zonking, and `ty` will be zonked (as this is a postcondition of `tcHsTypeApp`). But the function type `forall a. body` might not be fully zonked (hence the worry). But it's OK! During type checking, we don't require types to be well-kinded (without zonking); we only require them to satsisfy the Purely Kinded Type Invariant (PKTI). See Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType. In the case of a type application: * `forall a. body` satisfies the PKTI * `ty` is zonked * If we substitute a fully-zonked thing into an un-zonked Type that satisfies the PKTI, the result still satisfies the PKTI. This last statement isn't obvious, but read Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType. The tricky case is when `body` contains an application of the form `a b1 ... bn`, and we substitute `a :-> ty` where `ty` has fewer arrows in its kind than `a` does. That can't happen: the call `tcHsTypeApp hs_ty k` would have rejected the type application as ill-kinded. Historical remark: we used to require a stronger invariant than the PKTI, namely that all types are well-kinded prior to zonking. In that context, we did need to zonk `body` before performing the substitution above. See test case #14158, as well as the discussion in #23661.
References 1
- The Purely Kinded Type Invariant (PKTI) GHC.Tc.Gen.HsType
Referenced by 1
- GHC.Tc.Gen.App call site