Skip to content

Remove unnecessary uses of typeKind/tcTypeKind where possible

While perusing parts of the codebase related to coercions recently, I discovered this chunk of code in Inst:

get_eq_tys_maybe ty
  -- Lifted heterogeneous equality (~~)
  | Just (tc, [_, _, k1, k2]) <- splitTyConApp_maybe ty
  , tc `hasKey` heqTyConKey
  = Just (\co -> mkHEqBoxTy co k1 k2, k1, k2)

-- ...

mkHEqBoxTy :: TcCoercion -> Type -> Type -> TcM Type
mkHEqBoxTy co ty1 ty2
  = return $
    mkTyConApp (promoteDataCon heqDataCon) [k1, k2, ty1, ty2, mkCoercionTy co]
  where k1 = tcTypeKind ty1
        k2 = tcTypeKind ty2

There's something smelly going on in this code. in get_eq_tys_maybe, we call splitTyConApp_maybe to decompose an application of (~~), throwing the kind arguments away in the process. We then pass the type arguments k1 and k2 into mkHEqBoxTy. That function, in turn, constructs an application of HEq# using the arguments. But in the process of doing this, mkHEqBoxTy reconstructs the kinds of its arguments using tcTypeKind. This is incredibly wasteful, since we already have access to the kinds in get_eq_tys_maybe—we just ignore them at the moment. In general, tcTypeKind can be expensive to calculate, so it would be nice to avoid unnecessary uses of this function.

Luckily, it's simple to get rid of the uses of tcTypeKind in mkHEqBoxTy. get_eq_tys is the only place in GHC where mkHEqBoxTy is used, so we can simply change this code to the following:

get_eq_tys_maybe ty
  -- Lifted heterogeneous equality (~~)
  | Just (tc, [kk1, kk2, k1, k2]) <- splitTyConApp_maybe ty
  , tc `hasKey` heqTyConKey
  = Just (\co -> mkHEqBoxTy co kk1 kk2 k1 k2, k1, k2)

-- ...

mkHEqBoxTy :: TcCoercion -> Kind -> Kind -> Type -> Type -> TcM Type
mkHEqBoxTy co k1 k2 ty1 ty2
  = return $
    mkTyConApp (promoteDataCon heqDataCon) [k1, k2, ty1, ty2, mkCoercionTy co]

There are other places in GHC that call typeKind/tcTypeKind unnecessarily, but this was the most obvious one. I have a patch on the way which removes other unnecessary uses.

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