summaryrefslogtreecommitdiff
path: root/compiler/typecheck
diff options
context:
space:
mode:
authorningning <xnningxie@gmail.com>2018-07-09 20:02:03 -0400
committerRichard Eisenberg <rae@cs.brynmawr.edu>2018-07-09 21:35:31 -0400
commit55a3f8552c9dc9b84e204ec6623c698912795347 (patch)
tree3433832e7bc586c46cccd6204ce92748bc9b4a01 /compiler/typecheck
parent6595bee749ddb49d9058ed47ab7c1b6e7558ae17 (diff)
downloadhaskell-55a3f8552c9dc9b84e204ec6623c698912795347.tar.gz
Refactor coercion rule
Summary: The patch is an attempt on #15192. It defines a new coercion rule ``` | GRefl Role Type MCoercion ``` which correspondes to the typing rule ``` t1 : k1 ------------------------------------ GRefl r t1 MRefl: t1 ~r t1 t1 : k1 co :: k1 ~ k2 ------------------------------------ GRefl r t1 (MCo co) : t1 ~r t1 |> co ``` MCoercion wraps a coercion, which might be reflexive (MRefl) or not (MCo co). To know more about MCoercion see #14975. We keep Refl ty as a special case for nominal reflexive coercions, naemly, Refl ty :: ty ~n ty. This commit is meant to be a general performance improvement, but there are a few regressions. See #15192, comment:13 for more information. Test Plan: ./validate Reviewers: bgamari, goldfire, simonpj Subscribers: rwbarton, thomie, carter GHC Trac Issues: #15192 Differential Revision: https://phabricator.haskell.org/D4747
Diffstat (limited to 'compiler/typecheck')
-rw-r--r--compiler/typecheck/TcCanonical.hs21
-rw-r--r--compiler/typecheck/TcEvidence.hs14
-rw-r--r--compiler/typecheck/TcFlatten.hs85
-rw-r--r--compiler/typecheck/TcTyDecls.hs9
-rw-r--r--compiler/typecheck/TcType.hs7
-rw-r--r--compiler/typecheck/TcUnify.hs12
-rw-r--r--compiler/typecheck/TcValidity.hs8
7 files changed, 98 insertions, 58 deletions
diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs
index a8fff6b767..42f28c7c2b 100644
--- a/compiler/typecheck/TcCanonical.hs
+++ b/compiler/typecheck/TcCanonical.hs
@@ -1291,7 +1291,7 @@ canEqCast flat ev eq_rel swapped ty1 co1 ty2 ps_ty2
, ppr ty1 <+> text "|>" <+> ppr co1
, ppr ps_ty2 ])
; new_ev <- rewriteEqEvidence ev swapped ty1 ps_ty2
- (mkTcReflCo role ty1 `mkTcCoherenceRightCo` co1)
+ (mkTcGReflRightCo role ty1 co1)
(mkTcReflCo role ps_ty2)
; can_eq_nc flat new_ev eq_rel ty1 ty1 ty2 ps_ty2 }
where
@@ -1737,7 +1737,10 @@ canCFunEqCan ev fn tys fsk
-- new_co :: F tys' ~ new_fsk
-- co :: F tys ~ (new_fsk |> kind_co)
co = mkTcSymCo lhs_co `mkTcTransCo`
- (new_co `mkTcCoherenceRightCo` kind_co)
+ mkTcCoherenceRightCo Nominal
+ (mkTyVarTy new_fsk)
+ kind_co
+ new_co
; traceTcS "Discharging fmv/fsk due to hetero flattening" (ppr ev)
; dischargeFunEq ev fsk co xi
@@ -1788,7 +1791,7 @@ canEqTyVar ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2
new_rhs = xi2 `mkCastTy` rhs_kind_co
ps_rhs = ps_xi2 `mkCastTy` rhs_kind_co
- rhs_co = mkTcReflCo role xi2 `mkTcCoherenceLeftCo` rhs_kind_co
+ rhs_co = mkTcGReflLeftCo role xi2 rhs_kind_co
; new_ev <- rewriteEqEvidence ev swapped xi1 new_rhs
(mkTcReflCo role xi1) rhs_co
@@ -1803,8 +1806,8 @@ canEqTyVar ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2
new_rhs = xi2 `mkCastTy` sym_k2_co -- :: flat_k2
ps_rhs = ps_xi2 `mkCastTy` sym_k2_co
- lhs_co = mkReflCo role xi1 `mkTcCoherenceLeftCo` sym_k1_co
- rhs_co = mkReflCo role xi2 `mkTcCoherenceLeftCo` sym_k2_co
+ lhs_co = mkTcGReflLeftCo role xi1 sym_k1_co
+ rhs_co = mkTcGReflLeftCo role xi2 sym_k2_co
-- lhs_co :: (xi1 |> sym k1_co) ~ xi1
-- rhs_co :: (xi2 |> sym k2_co) ~ xi2
@@ -1841,11 +1844,11 @@ canEqTyVarHetero ev eq_rel tv1 co1 ki1 ps_tv1 xi2 ki2 ps_xi2
homo_co = mkTcSymCo (ctEvCoercion kind_ev) `mkTcTransCo` mkTcSymCo co1
rhs' = mkCastTy xi2 homo_co -- :: kind(tv1)
ps_rhs' = mkCastTy ps_xi2 homo_co -- :: kind(tv1)
- rhs_co = mkReflCo role xi2 `mkTcCoherenceLeftCo` homo_co
+ rhs_co = mkTcGReflLeftCo role xi2 homo_co
-- rhs_co :: (xi2 |> homo_co :: kind(tv1)) ~ xi2
lhs' = mkTyVarTy tv1 -- :: kind(tv1)
- lhs_co = mkReflCo role lhs' `mkTcCoherenceRightCo` co1
+ lhs_co = mkTcGReflRightCo role lhs' co1
-- lhs_co :: (tv1 :: kind(tv1)) ~ (tv1 |> co1 :: ki1)
; traceTcS "Hetero equality gives rise to given kind equality"
@@ -1895,10 +1898,10 @@ canEqTyVarHomo ev eq_rel swapped tv1 ps_ty1 ty2 _
sym_co2 = mkTcSymCo co2
ty1 = mkTyVarTy tv1
new_lhs = ty1 `mkCastTy` sym_co2
- lhs_co = mkReflCo role ty1 `mkTcCoherenceLeftCo` sym_co2
+ lhs_co = mkTcGReflLeftCo role ty1 sym_co2
new_rhs = mkTyVarTy tv2
- rhs_co = mkReflCo role new_rhs `mkTcCoherenceRightCo` co2
+ rhs_co = mkTcGReflRightCo role new_rhs co2
; new_ev <- rewriteEqEvidence ev swapped new_lhs new_rhs lhs_co rhs_co
diff --git a/compiler/typecheck/TcEvidence.hs b/compiler/typecheck/TcEvidence.hs
index 66fcb7a589..50c49bc65a 100644
--- a/compiler/typecheck/TcEvidence.hs
+++ b/compiler/typecheck/TcEvidence.hs
@@ -35,7 +35,9 @@ module TcEvidence (
mkTcAxInstCo, mkTcUnbranchedAxInstCo, mkTcForAllCo, mkTcForAllCos,
mkTcSymCo, mkTcTransCo, mkTcNthCo, mkTcLRCo, mkTcSubCo, maybeTcSubCo,
tcDowngradeRole,
- mkTcAxiomRuleCo, mkTcCoherenceLeftCo, mkTcCoherenceRightCo, mkTcPhantomCo,
+ mkTcAxiomRuleCo, mkTcGReflRightCo, mkTcGReflLeftCo, mkTcPhantomCo,
+ mkTcCoherenceLeftCo,
+ mkTcCoherenceRightCo,
mkTcKindCo,
tcCoercionKind, coVarsOfTcCo,
mkTcCoVarCo,
@@ -115,8 +117,12 @@ mkTcSubCo :: TcCoercionN -> TcCoercionR
maybeTcSubCo :: EqRel -> TcCoercion -> TcCoercion
tcDowngradeRole :: Role -> Role -> TcCoercion -> TcCoercion
mkTcAxiomRuleCo :: CoAxiomRule -> [TcCoercion] -> TcCoercionR
-mkTcCoherenceLeftCo :: TcCoercion -> TcCoercionN -> TcCoercion
-mkTcCoherenceRightCo :: TcCoercion -> TcCoercionN -> TcCoercion
+mkTcGReflRightCo :: Role -> TcType -> TcCoercionN -> TcCoercion
+mkTcGReflLeftCo :: Role -> TcType -> TcCoercionN -> TcCoercion
+mkTcCoherenceLeftCo :: Role -> TcType -> TcCoercionN
+ -> TcCoercion -> TcCoercion
+mkTcCoherenceRightCo :: Role -> TcType -> TcCoercionN
+ -> TcCoercion -> TcCoercion
mkTcPhantomCo :: TcCoercionN -> TcType -> TcType -> TcCoercionP
mkTcKindCo :: TcCoercion -> TcCoercionN
mkTcCoVarCo :: CoVar -> TcCoercion
@@ -148,6 +154,8 @@ mkTcSubCo = mkSubCo
maybeTcSubCo = maybeSubCo
tcDowngradeRole = downgradeRole
mkTcAxiomRuleCo = mkAxiomRuleCo
+mkTcGReflRightCo = mkGReflRightCo
+mkTcGReflLeftCo = mkGReflLeftCo
mkTcCoherenceLeftCo = mkCoherenceLeftCo
mkTcCoherenceRightCo = mkCoherenceRightCo
mkTcPhantomCo = mkPhantomCo
diff --git a/compiler/typecheck/TcFlatten.hs b/compiler/typecheck/TcFlatten.hs
index f6a1adf45e..ee13091681 100644
--- a/compiler/typecheck/TcFlatten.hs
+++ b/compiler/typecheck/TcFlatten.hs
@@ -1115,6 +1115,17 @@ as desired. (Why do we want Star? Because we started with something of kind Star
Whew.
+Note [flatten_exact_fam_app_fully performance]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The refactor of GRefl seems to cause performance trouble for T9872x: the allocation of flatten_exact_fam_app_fully_performance increased. See note [Generalized reflexive coercion] in TyCoRep for more information about GRefl and Trac #15192 for the current state.
+
+The explicit pattern match in homogenise_result helps with T9872a, b, c.
+
+Still, it increases the expected allocation of T9872d by ~2%.
+
+TODO: a step-by-step replay of the refactor to analyze the performance.
+
-}
{-# INLINE flatten_args_tc #-}
@@ -1208,12 +1219,12 @@ flatten_args_fast orig_binders orig_inner_ki orig_roles orig_tys
--
-- let kind_co = mkTcSymCo $ mkReflCo Nominal (tyBinderType binder)
-- casted_xi = xi `mkCastTy` kind_co
- -- casted_co = co `mkTcCoherenceLeftCo` kind_co
+ -- casted_co = xi |> kind_co ~r xi ; co
--
-- but this isn't necessary:
-- mkTcSymCo (Refl a b) = Refl a b,
-- mkCastTy x (Refl _ _) = x
- -- mkTcCoherenceLeftCo x (Refl _ _) = x
+ -- mkTcGReflLeftCo _ ty (Refl _ _) `mkTransCo` co = co
--
-- Also, no need to check isAnonTyBinder or isNamedTyBinder, since
-- we've already established that they're all anonymous.
@@ -1229,7 +1240,7 @@ flatten_args_fast orig_binders orig_inner_ki orig_roles orig_tys
finish (xis, cos, binders) = (xis, cos, kind_co)
where
final_kind = mkPiTys binders orig_inner_ki
- kind_co = mkReflCo Nominal final_kind
+ kind_co = mkNomReflCo final_kind
{-# INLINE flatten_args_slow #-}
-- | Slow path, compared to flatten_args_fast, because this one must track
@@ -1283,7 +1294,7 @@ flatten_args_slow orig_binders orig_inner_ki orig_fvs orig_roles orig_tys
; let kind_co = mkTcSymCo $
liftCoSubst Nominal lc (tyBinderType binder)
!casted_xi = xi `mkCastTy` kind_co
- casted_co = co `mkTcCoherenceLeftCo` kind_co
+ casted_co = mkTcCoherenceLeftCo role xi kind_co co
-- now, extend the lifting context with the new binding
!new_lc | Just tv <- tyBinderVar_maybe binder
@@ -1314,13 +1325,13 @@ flatten_args_slow orig_binders orig_inner_ki orig_fvs orig_roles orig_tys
<- go acc_xis acc_cos zapped_lc bndrs new_inner roles casted_tys
-- cos_out :: xis_out ~ casted_tys
-- we need to return cos :: xis_out ~ tys
- --
- -- zipWith has the map first because it will fuse.
- ; let cos = zipWith (flip mkTcCoherenceRightCo)
- (map mkTcSymCo arg_cos)
- cos_out
+ ; let cos = zipWith3 mkTcGReflRightCo
+ roles
+ casted_tys
+ (map mkTcSymCo arg_cos)
+ cos' = zipWith mkTransCo cos_out cos
- ; return (xis_out, cos, res_co_out `mkTcTransCo` res_co) }
+ ; return (xis_out, cos', res_co_out `mkTcTransCo` res_co) }
go _ _ _ _ _ _ _ = pprPanic
"flatten_args wandered into deeper water than usual" (vcat [])
@@ -1408,7 +1419,8 @@ flatten_one (CastTy ty g)
= do { (xi, co) <- flatten_one ty
; (g', _) <- flatten_co g
- ; return (mkCastTy xi g', castCoercionKind co g' g) }
+ ; role <- getRole
+ ; return (mkCastTy xi g', castCoercionKind co role xi ty g' g) }
flatten_one (CoercionTy co) = first mkCoercionTy <$> flatten_co co
@@ -1471,7 +1483,8 @@ flatten_app_ty_args fun_xi fun_co arg_tys
arg_co = mkAppCos fun_co arg_cos
; return (arg_xi, arg_co, kind_co) }
- ; return (homogenise_result xi co kind_co) }
+ ; role <- getRole
+ ; return (homogenise_result xi co role kind_co) }
flatten_ty_con_app :: TyCon -> [TcType] -> FlatM (Xi, Coercion)
flatten_ty_con_app tc tys
@@ -1479,18 +1492,21 @@ flatten_ty_con_app tc tys
; (xis, cos, kind_co) <- flatten_args_tc tc (tyConRolesX role tc) tys
; let tyconapp_xi = mkTyConApp tc xis
tyconapp_co = mkTyConAppCo role tc cos
- ; return (homogenise_result tyconapp_xi tyconapp_co kind_co) }
+ ; return (homogenise_result tyconapp_xi tyconapp_co role kind_co) }
-- Make the result of flattening homogeneous (Note [Flattening] (F2))
homogenise_result :: Xi -- a flattened type
- -> Coercion -- :: xi ~ original ty
+ -> Coercion -- :: xi ~r original ty
+ -> Role -- r
-> CoercionN -- kind_co :: typeKind(xi) ~N typeKind(ty)
-> (Xi, Coercion) -- (xi |> kind_co, (xi |> kind_co)
- -- ~ original ty)
-homogenise_result xi co kind_co
- = let xi' = xi `mkCastTy` kind_co
- co' = co `mkTcCoherenceLeftCo` kind_co
- in (xi', co')
+ -- ~r original ty)
+homogenise_result xi co r kind_co
+ -- the explicit pattern match here improves the performance of T9872a, b, c by
+ -- ~2%
+ | isGReflCo kind_co = (xi `mkCastTy` kind_co, co)
+ | otherwise = (xi `mkCastTy` kind_co
+ , (mkSymCo $ GRefl r xi (MCo kind_co)) `mkTransCo` co)
{-# INLINE homogenise_result #-}
-- Flatten a vector (list of arguments).
@@ -1588,6 +1604,7 @@ flatten_fam_app tc tys -- Can be over-saturated
; flatten_app_ty_args xi1 co1 tys_rest } } }
-- the [TcType] exactly saturate the TyCon
+-- See note [flatten_exact_fam_app_fully performance]
flatten_exact_fam_app_fully :: TyCon -> [TcType] -> FlatM (Xi, Coercion)
flatten_exact_fam_app_fully tc tys
-- See Note [Reduce type family applications eagerly]
@@ -1625,10 +1642,10 @@ flatten_exact_fam_app_fully tc tys
-- flatten it
-- fsk_co :: fsk_xi ~ fsk
; let xi = fsk_xi `mkCastTy` kind_co
- co' = (fsk_co `mkTcCoherenceLeftCo` kind_co)
- `mkTransCo`
- maybeSubCo eq_rel (mkSymCo co)
- `mkTransCo` ret_co
+ co' = mkTcCoherenceLeftCo role fsk_xi kind_co fsk_co
+ `mkTransCo`
+ maybeSubCo eq_rel (mkSymCo co)
+ `mkTransCo` ret_co
; return (xi, co')
}
-- :: fsk_xi ~ F xis
@@ -1658,12 +1675,12 @@ flatten_exact_fam_app_fully tc tys
; traceFlat "flatten/flat-cache miss" $
(ppr tc <+> ppr xis $$ ppr fsk $$ ppr ev)
- -- NB: fsk's kind is already flattend because
+ -- NB: fsk's kind is already flattened because
-- the xis are flattened
- ; let xi = mkTyVarTy fsk `mkCastTy` kind_co
- co' = (maybeSubCo eq_rel (mkSymCo co)
- `mkTcCoherenceLeftCo` kind_co)
- `mkTransCo` ret_co
+ ; let fsk_ty = mkTyVarTy fsk
+ xi = fsk_ty `mkCastTy` kind_co
+ co' = mkTcCoherenceLeftCo role fsk_ty kind_co (maybeSubCo eq_rel (mkSymCo co))
+ `mkTransCo` ret_co
; return (xi, co')
}
}
@@ -1707,9 +1724,10 @@ flatten_exact_fam_app_fully tc tys
; when (eq_rel == NomEq) $
liftTcS $
extendFlatCache tc tys ( co, xi, flavour )
- ; let xi' = xi `mkCastTy` kind_co
- co' = update_co $ mkSymCo co
- `mkTcCoherenceLeftCo` kind_co
+ ; let role = eqRelRole eq_rel
+ xi' = xi `mkCastTy` kind_co
+ co' = update_co $
+ mkTcCoherenceLeftCo role xi kind_co (mkSymCo co)
; return $ Just (xi', co') }
Nothing -> pure Nothing }
@@ -1735,9 +1753,10 @@ flatten_exact_fam_app_fully tc tys
; eq_rel <- getEqRel
; let co = maybeSubCo eq_rel norm_co
`mkTransCo` mkSymCo final_co
+ role = eqRelRole eq_rel
xi' = xi `mkCastTy` kind_co
- co' = update_co $ mkSymCo co
- `mkTcCoherenceLeftCo` kind_co
+ co' = update_co $
+ mkTcCoherenceLeftCo role xi kind_co (mkSymCo co)
; return $ Just (xi', co') }
Nothing -> pure Nothing }
diff --git a/compiler/typecheck/TcTyDecls.hs b/compiler/typecheck/TcTyDecls.hs
index cce0f02a0b..f64b9f3e73 100644
--- a/compiler/typecheck/TcTyDecls.hs
+++ b/compiler/typecheck/TcTyDecls.hs
@@ -32,7 +32,7 @@ import GhcPrelude
import TcRnMonad
import TcEnv
import TcBinds( tcValBinds, addTypecheckedBinds )
-import TyCoRep( Type(..), Coercion(..), UnivCoProvenance(..) )
+import TyCoRep( Type(..), Coercion(..), MCoercion(..), UnivCoProvenance(..) )
import TcType
import TysWiredIn( unitTy )
import MkCore( rEC_SEL_ERROR_ID )
@@ -111,7 +111,11 @@ synonymTyConsOfType ty
-- in the same recursive group. Possibly this restriction will be
-- lifted in the future but for now, this code is "just for completeness
-- sake".
- go_co (Refl _ ty) = go ty
+ go_mco MRefl = emptyNameEnv
+ go_mco (MCo co) = go_co co
+
+ go_co (Refl ty) = go ty
+ go_co (GRefl _ ty mco) = go ty `plusNameEnv` go_mco mco
go_co (TyConAppCo _ tc cs) = go_tc tc `plusNameEnv` go_co_s cs
go_co (AppCo co co') = go_co co `plusNameEnv` go_co co'
go_co (ForAllCo _ co co') = go_co co `plusNameEnv` go_co co'
@@ -125,7 +129,6 @@ synonymTyConsOfType ty
go_co (NthCo _ _ co) = go_co co
go_co (LRCo _ co) = go_co co
go_co (InstCo co co') = go_co co `plusNameEnv` go_co co'
- go_co (CoherenceCo co co') = go_co co `plusNameEnv` go_co co'
go_co (KindCo co) = go_co co
go_co (SubCo co) = go_co co
go_co (AxiomRuleCo _ cs) = go_co_s cs
diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs
index 092c5a1923..00bae72117 100644
--- a/compiler/typecheck/TcType.hs
+++ b/compiler/typecheck/TcType.hs
@@ -936,7 +936,11 @@ exactTyCoVarsOfType ty
go (CastTy ty co) = go ty `unionVarSet` goCo co
go (CoercionTy co) = goCo co
- goCo (Refl _ ty) = go ty
+ goMCo MRefl = emptyVarSet
+ goMCo (MCo co) = goCo co
+
+ goCo (Refl ty) = go ty
+ goCo (GRefl _ ty mco) = go ty `unionVarSet` goMCo mco
goCo (TyConAppCo _ _ args)= goCos args
goCo (AppCo co arg) = goCo co `unionVarSet` goCo arg
goCo (ForAllCo tv k_co co)
@@ -951,7 +955,6 @@ exactTyCoVarsOfType ty
goCo (NthCo _ _ co) = goCo co
goCo (LRCo _ co) = goCo co
goCo (InstCo co arg) = goCo co `unionVarSet` goCo arg
- goCo (CoherenceCo c1 c2) = goCo c1 `unionVarSet` goCo c2
goCo (KindCo co) = goCo co
goCo (SubCo co) = goCo co
goCo (AxiomRuleCo _ c) = goCos c
diff --git a/compiler/typecheck/TcUnify.hs b/compiler/typecheck/TcUnify.hs
index eb44bc385f..08a5c59879 100644
--- a/compiler/typecheck/TcUnify.hs
+++ b/compiler/typecheck/TcUnify.hs
@@ -971,7 +971,7 @@ promoteTcType dest_lvl ty
, uo_thing = Nothing
, uo_visible = False }
; ki_co <- uType KindLevel kind_orig (typeKind ty) res_kind
- ; let co = mkTcNomReflCo ty `mkTcCoherenceRightCo` ki_co
+ ; let co = mkTcGReflRightCo Nominal ty ki_co
; return (co, ty `mkCastTy` ki_co) }
{- Note [Promoting a type]
@@ -1265,7 +1265,7 @@ uType, uType_defer
-> CtOrigin
-> TcType -- ty1 is the *actual* type
-> TcType -- ty2 is the *expected* type
- -> TcM Coercion
+ -> TcM CoercionN
--------------
-- It is always safe to defer unification to the main constraint solver
@@ -1300,7 +1300,7 @@ uType t_or_k origin orig_ty1 orig_ty2
else traceTc "u_tys yields coercion:" (ppr co)
; return co }
where
- go :: TcType -> TcType -> TcM Coercion
+ go :: TcType -> TcType -> TcM CoercionN
-- The arguments to 'go' are always semantically identical
-- to orig_ty{1,2} except for looking through type synonyms
@@ -1324,15 +1324,15 @@ uType t_or_k origin orig_ty1 orig_ty2
-- See Note [Expanding synonyms during unification]
go ty1@(TyConApp tc1 []) (TyConApp tc2 [])
| tc1 == tc2
- = return $ mkReflCo Nominal ty1
+ = return $ mkNomReflCo ty1
go (CastTy t1 co1) t2
= do { co_tys <- go t1 t2
- ; return (mkCoherenceLeftCo co_tys co1) }
+ ; return (mkCoherenceLeftCo Nominal t1 co1 co_tys) }
go t1 (CastTy t2 co2)
= do { co_tys <- go t1 t2
- ; return (mkCoherenceRightCo co_tys co2) }
+ ; return ( mkCoherenceRightCo Nominal t2 co2 co_tys) }
-- See Note [Expanding synonyms during unification]
--
diff --git a/compiler/typecheck/TcValidity.hs b/compiler/typecheck/TcValidity.hs
index 60fb2618c3..d51fa9d4b6 100644
--- a/compiler/typecheck/TcValidity.hs
+++ b/compiler/typecheck/TcValidity.hs
@@ -2030,8 +2030,13 @@ fvType (CoercionTy co) = fvCo co
fvTypes :: [Type] -> [TyVar]
fvTypes tys = concat (map fvType tys)
+fvMCo :: MCoercion -> [TyCoVar]
+fvMCo MRefl = []
+fvMCo (MCo co) = fvCo co
+
fvCo :: Coercion -> [TyCoVar]
-fvCo (Refl _ ty) = fvType ty
+fvCo (Refl ty) = fvType ty
+fvCo (GRefl _ ty mco) = fvType ty ++ fvMCo mco
fvCo (TyConAppCo _ _ args) = concatMap fvCo args
fvCo (AppCo co arg) = fvCo co ++ fvCo arg
fvCo (ForAllCo tv h co) = filter (/= tv) (fvCo co) ++ fvCo h
@@ -2044,7 +2049,6 @@ fvCo (TransCo co1 co2) = fvCo co1 ++ fvCo co2
fvCo (NthCo _ _ co) = fvCo co
fvCo (LRCo _ co) = fvCo co
fvCo (InstCo co arg) = fvCo co ++ fvCo arg
-fvCo (CoherenceCo co1 co2) = fvCo co1 ++ fvCo co2
fvCo (KindCo co) = fvCo co
fvCo (SubCo co) = fvCo co
fvCo (AxiomRuleCo _ cs) = concatMap fvCo cs