diff options
author | ningning <xnningxie@gmail.com> | 2018-07-09 20:02:03 -0400 |
---|---|---|
committer | Richard Eisenberg <rae@cs.brynmawr.edu> | 2018-07-09 21:35:31 -0400 |
commit | 55a3f8552c9dc9b84e204ec6623c698912795347 (patch) | |
tree | 3433832e7bc586c46cccd6204ce92748bc9b4a01 /compiler/typecheck | |
parent | 6595bee749ddb49d9058ed47ab7c1b6e7558ae17 (diff) | |
download | haskell-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.hs | 21 | ||||
-rw-r--r-- | compiler/typecheck/TcEvidence.hs | 14 | ||||
-rw-r--r-- | compiler/typecheck/TcFlatten.hs | 85 | ||||
-rw-r--r-- | compiler/typecheck/TcTyDecls.hs | 9 | ||||
-rw-r--r-- | compiler/typecheck/TcType.hs | 7 | ||||
-rw-r--r-- | compiler/typecheck/TcUnify.hs | 12 | ||||
-rw-r--r-- | compiler/typecheck/TcValidity.hs | 8 |
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 |