Skip to content

`tcMatchTy` is terribly broken

Suppose (T :: forall k. k -> Type) and we are matching

   tcMatchTy (T k (a::k))  (T j (b::j))

Then we'll match k :-> j, as expected. But then in TcUnify.unify_tys we invoke

   unify_tys env (a::k) (b::j) (Refl k)

Despite Note [Kind coercions in Unify] it's not clear to me why we need that Refl coercion.

But, assuming we need it, very very bad things now happen. In uUnrefined we end up adding the binding a :-> (b |> Refl k).

Alas! Alack! k is one of the template variables, which we are substituting away, so it's terrible if k appears in the range of the substitution -- it belongs only in the range.

A one-line (actually one-character) fix is this:

-      = do { unify_ty env x y (mkNomReflCo $ typeKind x)
+      = do { unify_ty env x y (mkNomReflCo $ typeKind y)

But I am hard-pressed to explain exactly why this is the correct fix.

@rae, help?

This actually bit me when working on mkCastTy in #17323.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information