diff options
-rw-r--r-- | compiler/coreSyn/CoreLint.lhs | 13 | ||||
-rw-r--r-- | compiler/coreSyn/ExternalCore.lhs | 3 | ||||
-rw-r--r-- | compiler/coreSyn/MkExternalCore.lhs | 5 | ||||
-rw-r--r-- | compiler/coreSyn/PprExternalCore.lhs | 4 | ||||
-rw-r--r-- | compiler/coreSyn/TrieMap.lhs | 22 | ||||
-rw-r--r-- | compiler/deSugar/DsBinds.lhs | 1 | ||||
-rw-r--r-- | compiler/iface/BinIface.hs | 14 | ||||
-rw-r--r-- | compiler/iface/IfaceType.lhs | 5 | ||||
-rw-r--r-- | compiler/iface/TcIface.lhs | 1 | ||||
-rw-r--r-- | compiler/typecheck/TcCanonical.lhs | 14 | ||||
-rw-r--r-- | compiler/typecheck/TcEvidence.lhs | 14 | ||||
-rw-r--r-- | compiler/typecheck/TcHsSyn.lhs | 1 | ||||
-rw-r--r-- | compiler/typecheck/TcType.lhs | 1 | ||||
-rw-r--r-- | compiler/types/Coercion.lhs | 31 | ||||
-rw-r--r-- | compiler/types/OptCoercion.lhs | 56 |
15 files changed, 152 insertions, 33 deletions
diff --git a/compiler/coreSyn/CoreLint.lhs b/compiler/coreSyn/CoreLint.lhs index dcd366f381..250efdd85d 100644 --- a/compiler/coreSyn/CoreLint.lhs +++ b/compiler/coreSyn/CoreLint.lhs @@ -838,6 +838,19 @@ lintCoercion the_co@(NthCo n co) _ -> failWithL (hang (ptext (sLit "Bad getNth:")) 2 (ppr the_co $$ ppr s $$ ppr t)) } +lintCoercion the_co@(LRCo lr co) + = do { (_,s,t) <- lintCoercion co + ; case (splitAppTy_maybe s, splitAppTy_maybe t) of + (Just s_pr, Just t_pr) + -> return (k, s_pick, t_pick) + where + s_pick = pickLR lr s_pr + t_pick = pickLR lr t_pr + k = typeKind s_pick + + _ -> failWithL (hang (ptext (sLit "Bad LRCo:")) + 2 (ppr the_co $$ ppr s $$ ppr t)) } + lintCoercion (InstCo co arg_ty) = do { (k,s,t) <- lintCoercion co ; arg_kind <- lintType arg_ty diff --git a/compiler/coreSyn/ExternalCore.lhs b/compiler/coreSyn/ExternalCore.lhs index d2f6691a7c..287f08049e 100644 --- a/compiler/coreSyn/ExternalCore.lhs +++ b/compiler/coreSyn/ExternalCore.lhs @@ -74,6 +74,9 @@ data Ty | UnsafeCoercion Ty Ty | InstCoercion Ty Ty | NthCoercion Int Ty + | LRCoercion LeftOrRight Ty + +data LeftOrRight = CLeft | CRight data Kind = Klifted diff --git a/compiler/coreSyn/MkExternalCore.lhs b/compiler/coreSyn/MkExternalCore.lhs index 21037088e1..8844818bdc 100644 --- a/compiler/coreSyn/MkExternalCore.lhs +++ b/compiler/coreSyn/MkExternalCore.lhs @@ -326,8 +326,13 @@ make_co dflags (UnsafeCo t1 t2) = C.UnsafeCoercion (make_ty dflags t1) (mak make_co dflags (SymCo co) = C.SymCoercion (make_co dflags co) make_co dflags (TransCo c1 c2) = C.TransCoercion (make_co dflags c1) (make_co dflags c2) make_co dflags (NthCo d co) = C.NthCoercion d (make_co dflags co) +make_co dflags (LRCo lr co) = C.LRCoercion (make_lr lr) (make_co dflags co) make_co dflags (InstCo co ty) = C.InstCoercion (make_co dflags co) (make_ty dflags ty) +make_lr :: LeftOrRight -> C.LeftOrRight +make_lr CLeft = C.CLeft +make_lr CRight = C.CRight + -- Used for both tycon app coercions and axiom instantiations. make_conAppCo :: DynFlags -> C.Qual C.Tcon -> [Coercion] -> C.Ty make_conAppCo dflags con cos = diff --git a/compiler/coreSyn/PprExternalCore.lhs b/compiler/coreSyn/PprExternalCore.lhs index 26e64ee641..2290810fe1 100644 --- a/compiler/coreSyn/PprExternalCore.lhs +++ b/compiler/coreSyn/PprExternalCore.lhs @@ -114,6 +114,10 @@ pty (UnsafeCoercion t1 t2) = sep [text "%unsafe", paty t1, paty t2] pty (NthCoercion n t) = sep [text "%nth", int n, paty t] +pty (LRCoercion CLeft t) = + sep [text "%left", paty t] +pty (LRCoercion CRight t) = + sep [text "%right", paty t] pty (InstCoercion t1 t2) = sep [text "%inst", paty t1, paty t2] pty t = pbty t diff --git a/compiler/coreSyn/TrieMap.lhs b/compiler/coreSyn/TrieMap.lhs index 7170f1cede..6bc78a8272 100644 --- a/compiler/coreSyn/TrieMap.lhs +++ b/compiler/coreSyn/TrieMap.lhs @@ -470,6 +470,8 @@ data CoercionMap a , km_sym :: CoercionMap a , km_trans :: CoercionMap (CoercionMap a) , km_nth :: IntMap.IntMap (CoercionMap a) + , km_left :: CoercionMap a + , km_right :: CoercionMap a , km_inst :: CoercionMap (TypeMap a) } wrapEmptyKM :: CoercionMap a @@ -477,7 +479,8 @@ wrapEmptyKM = KM { km_refl = emptyTM, km_tc_app = emptyNameEnv , km_app = emptyTM, km_forall = emptyTM , km_var = emptyTM, km_axiom = emptyNameEnv , km_unsafe = emptyTM, km_sym = emptyTM, km_trans = emptyTM - , km_nth = emptyTM, km_inst = emptyTM } + , km_nth = emptyTM, km_left = emptyTM, km_right = emptyTM + , km_inst = emptyTM } instance TrieMap CoercionMap where type Key CoercionMap = Coercion @@ -493,7 +496,8 @@ mapC f (KM { km_refl = krefl, km_tc_app = ktc , km_app = kapp, km_forall = kforall , km_var = kvar, km_axiom = kax , km_unsafe = kunsafe, km_sym = ksym, km_trans = ktrans - , km_nth = knth, km_inst = kinst }) + , km_nth = knth, km_left = kml, km_right = kmr + , km_inst = kinst }) = KM { km_refl = mapTM f krefl , km_tc_app = mapNameEnv (mapTM f) ktc , km_app = mapTM (mapTM f) kapp @@ -504,6 +508,8 @@ mapC f (KM { km_refl = krefl, km_tc_app = ktc , km_sym = mapTM f ksym , km_trans = mapTM (mapTM f) ktrans , km_nth = IntMap.map (mapTM f) knth + , km_left = mapTM f kml + , km_right = mapTM f kmr , km_inst = mapTM (mapTM f) kinst } lkC :: CmEnv -> Coercion -> CoercionMap a -> Maybe a @@ -522,6 +528,8 @@ lkC env co m go (CoVarCo v) = km_var >.> lkVar env v go (SymCo c) = km_sym >.> lkC env c go (NthCo n c) = km_nth >.> lookupTM n >=> lkC env c + go (LRCo CLeft c) = km_left >.> lkC env c + go (LRCo CRight c) = km_right >.> lkC env c xtC :: CmEnv -> Coercion -> XT a -> CoercionMap a -> CoercionMap a xtC env co f EmptyKM = xtC env co f wrapEmptyKM @@ -534,9 +542,11 @@ xtC env (UnsafeCo t1 t2) f m = m { km_unsafe = km_unsafe m |> xtT env t1 |>> xtC env (InstCo c t) f m = m { km_inst = km_inst m |> xtC env c |>> xtT env t f } xtC env (ForAllCo v c) f m = m { km_forall = km_forall m |> xtC (extendCME env v) c |>> xtBndr env v f } -xtC env (CoVarCo v) f m = m { km_var = km_var m |> xtVar env v f } -xtC env (SymCo c) f m = m { km_sym = km_sym m |> xtC env c f } -xtC env (NthCo n c) f m = m { km_nth = km_nth m |> xtInt n |>> xtC env c f } +xtC env (CoVarCo v) f m = m { km_var = km_var m |> xtVar env v f } +xtC env (SymCo c) f m = m { km_sym = km_sym m |> xtC env c f } +xtC env (NthCo n c) f m = m { km_nth = km_nth m |> xtInt n |>> xtC env c f } +xtC env (LRCo CLeft c) f m = m { km_left = km_left m |> xtC env c f } +xtC env (LRCo CRight c) f m = m { km_right = km_right m |> xtC env c f } fdC :: (a -> b -> b) -> CoercionMap a -> b -> b fdC _ EmptyKM = \z -> z @@ -550,6 +560,8 @@ fdC k m = foldTM k (km_refl m) . foldTM k (km_sym m) . foldTM (foldTM k) (km_trans m) . foldTM (foldTM k) (km_nth m) + . foldTM k (km_left m) + . foldTM k (km_right m) . foldTM (foldTM k) (km_inst m) \end{code} diff --git a/compiler/deSugar/DsBinds.lhs b/compiler/deSugar/DsBinds.lhs index 803cdd886e..b418c8d592 100644 --- a/compiler/deSugar/DsBinds.lhs +++ b/compiler/deSugar/DsBinds.lhs @@ -834,6 +834,7 @@ ds_tc_coercion subst tc_co go (TcSymCo co) = mkSymCo (go co) go (TcTransCo co1 co2) = mkTransCo (go co1) (go co2) go (TcNthCo n co) = mkNthCo n (go co) + go (TcLRCo lr co) = mkLRCo lr (go co) go (TcInstCo co ty) = mkInstCo (go co) ty go (TcLetCo bs co) = ds_tc_coercion (ds_co_binds bs) co go (TcCastCo co1 co2) = mkCoCast (go co1) (go co2) diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs index a319f6ed62..362df3fc35 100644 --- a/compiler/iface/BinIface.hs +++ b/compiler/iface/BinIface.hs @@ -20,11 +20,12 @@ module BinIface ( #include "HsVersions.h" import TcRnMonad -import TyCon (TyCon, tyConName, tupleTyConSort, tupleTyConArity, isTupleTyCon) +import TyCon import DataCon (dataConName, dataConWorkId, dataConTyCon) import PrelInfo (wiredInThings, basicKnownKeyNames) import Id (idName, isDataConWorkId_maybe) import CoreSyn (DFunArg(..)) +import Coercion (LeftOrRight(..)) import TysWiredIn import IfaceEnv import HscTypes @@ -1037,6 +1038,15 @@ instance Binary IfaceTyCon where put_ bh (IfaceTc ext) = put_ bh ext get bh = liftM IfaceTc (get bh) +instance Binary LeftOrRight where + put_ bh CLeft = putByte bh 0 + put_ bh CRight = putByte bh 1 + + get bh = do { h <- getByte bh + ; case h of + 0 -> return CLeft + _ -> return CRight } + instance Binary IfaceCoCon where put_ bh (IfaceCoAx n) = do { putByte bh 0; put_ bh n } put_ bh IfaceReflCo = putByte bh 1 @@ -1045,6 +1055,7 @@ instance Binary IfaceCoCon where put_ bh IfaceTransCo = putByte bh 4 put_ bh IfaceInstCo = putByte bh 5 put_ bh (IfaceNthCo d) = do { putByte bh 6; put_ bh d } + put_ bh (IfaceLRCo lr) = do { putByte bh 7; put_ bh lr } get bh = do h <- getByte bh @@ -1056,6 +1067,7 @@ instance Binary IfaceCoCon where 4 -> return IfaceTransCo 5 -> return IfaceInstCo 6 -> do { d <- get bh; return (IfaceNthCo d) } + 7 -> do { lr <- get bh; return (IfaceLRCo lr) } _ -> panic ("get IfaceCoCon " ++ show h) ------------------------------------------------------------------------- diff --git a/compiler/iface/IfaceType.lhs b/compiler/iface/IfaceType.lhs index 225a3c812b..4a35f0049b 100644 --- a/compiler/iface/IfaceType.lhs +++ b/compiler/iface/IfaceType.lhs @@ -99,7 +99,7 @@ data IfaceCoCon = IfaceCoAx IfExtName | IfaceReflCo | IfaceUnsafeCo | IfaceSymCo | IfaceTransCo | IfaceInstCo - | IfaceNthCo Int + | IfaceNthCo Int | IfaceLRCo LeftOrRight \end{code} %************************************************************************ @@ -278,6 +278,7 @@ instance Outputable IfaceCoCon where ppr IfaceTransCo = ptext (sLit "Trans") ppr IfaceInstCo = ptext (sLit "Inst") ppr (IfaceNthCo d) = ptext (sLit "Nth:") <> int d + ppr (IfaceLRCo lr) = ppr lr instance Outputable IfaceTyLit where ppr = ppr_tylit @@ -376,6 +377,8 @@ coToIfaceType (TransCo co1 co2) = IfaceCoConApp IfaceTransCo , coToIfaceType co2 ] coToIfaceType (NthCo d co) = IfaceCoConApp (IfaceNthCo d) [ coToIfaceType co ] +coToIfaceType (LRCo lr co) = IfaceCoConApp (IfaceLRCo lr) + [ coToIfaceType co ] coToIfaceType (InstCo co ty) = IfaceCoConApp IfaceInstCo [ coToIfaceType co , toIfaceType ty ] diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs index 80c2029a70..eb9e5ddb80 100644 --- a/compiler/iface/TcIface.lhs +++ b/compiler/iface/TcIface.lhs @@ -962,6 +962,7 @@ tcIfaceCoApp IfaceSymCo [t] = SymCo <$> tcIfaceCo t tcIfaceCoApp IfaceTransCo [t1,t2] = TransCo <$> tcIfaceCo t1 <*> tcIfaceCo t2 tcIfaceCoApp IfaceInstCo [t1,t2] = InstCo <$> tcIfaceCo t1 <*> tcIfaceType t2 tcIfaceCoApp (IfaceNthCo d) [t] = NthCo d <$> tcIfaceCo t +tcIfaceCoApp (IfaceLRCo lr) [t] = LRCo lr <$> tcIfaceCo t tcIfaceCoApp cc ts = pprPanic "toIfaceCoApp" (ppr cc <+> ppr ts) tcIfaceCoVar :: FastString -> IfL CoVar diff --git a/compiler/typecheck/TcCanonical.lhs b/compiler/typecheck/TcCanonical.lhs index e755d69c6b..dbb9de1365 100644 --- a/compiler/typecheck/TcCanonical.lhs +++ b/compiler/typecheck/TcCanonical.lhs @@ -809,19 +809,11 @@ canEqAppTy :: CtLoc -> CtEvidence -> TcS StopOrContinue canEqAppTy loc ev s1 t1 s2 t2 = ASSERT( not (isKind t1) && not (isKind t2) ) - if isGiven ev then - do { traceTcS "canEq (app case)" $ - text "Ommitting decomposition of given equality between: " - <+> ppr (AppTy s1 t1) <+> text "and" <+> ppr (AppTy s2 t2) - -- We cannot decompose given applications - -- because we no longer have 'left' and 'right' - ; return Stop } - else do { let xevcomp [x,y] = EvCoercion (mkTcAppCo (evTermCoercion x) (evTermCoercion y)) xevcomp _ = error "canEqAppTy: can't happen" -- Can't happen - xev = XEvTerm { ev_comp = xevcomp - , ev_decomp = error "canEqAppTy: can't happen" } - ; ctevs <- xCtFlavor ev [mkTcEqPred s1 s2, mkTcEqPred t1 t2] xev + xevdecomp x = let xco = evTermCoercion x + in [EvCoercion (mkTcLRCo CLeft xco), EvCoercion (mkTcLRCo CRight xco)] + ; ctevs <- xCtFlavor ev [mkTcEqPred s1 s2, mkTcEqPred t1 t2] (XEvTerm xevcomp xevdecomp) ; canEvVarsCreated loc ctevs } canEqFailure :: CtLoc -> CtEvidence -> TcS StopOrContinue diff --git a/compiler/typecheck/TcEvidence.lhs b/compiler/typecheck/TcEvidence.lhs index 321809f91d..c88b350616 100644 --- a/compiler/typecheck/TcEvidence.lhs +++ b/compiler/typecheck/TcEvidence.lhs @@ -20,10 +20,10 @@ module TcEvidence ( EvLit(..), evTermCoercion, -- TcCoercion - TcCoercion(..), + TcCoercion(..), LeftOrRight(..), pickLR, mkTcReflCo, mkTcTyConAppCo, mkTcAppCo, mkTcAppCos, mkTcFunCo, mkTcAxInstCo, mkTcForAllCo, mkTcForAllCos, - mkTcSymCo, mkTcTransCo, mkTcNthCo, mkTcInstCos, + mkTcSymCo, mkTcTransCo, mkTcNthCo, mkTcLRCo, mkTcInstCos, tcCoercionKind, coVarsOfTcCo, isEqVar, mkTcCoVarCo, isTcReflCo, isTcReflCo_maybe, getTcCoVar_maybe, liftTcCoSubstWith @@ -32,7 +32,7 @@ module TcEvidence ( #include "HsVersions.h" import Var - +import Coercion( LeftOrRight(..), pickLR ) import PprCore () -- Instance OutputableBndr TyVar import TypeRep -- Knows type representation import TcType @@ -102,6 +102,7 @@ data TcCoercion | TcSymCo TcCoercion | TcTransCo TcCoercion TcCoercion | TcNthCo Int TcCoercion + | TcLRCo LeftOrRight TcCoercion | TcCastCo TcCoercion TcCoercion -- co1 |> co2 | TcLetCo TcEvBinds TcCoercion deriving (Data.Data, Data.Typeable) @@ -167,6 +168,10 @@ mkTcNthCo :: Int -> TcCoercion -> TcCoercion mkTcNthCo n (TcRefl ty) = TcRefl (tyConAppArgN n ty) mkTcNthCo n co = TcNthCo n co +mkTcLRCo :: LeftOrRight -> TcCoercion -> TcCoercion +mkTcLRCo lr (TcRefl ty) = TcRefl (pickLR lr (tcSplitAppTy ty)) +mkTcLRCo lr co = TcLRCo lr co + mkTcAppCos :: TcCoercion -> [TcCoercion] -> TcCoercion mkTcAppCos co1 tys = foldl mkTcAppCo co1 tys @@ -211,6 +216,7 @@ tcCoercionKind co = go co go (TcSymCo co) = swap (go co) go (TcTransCo co1 co2) = Pair (pFst (go co1)) (pSnd (go co2)) go (TcNthCo d co) = tyConAppArgN d <$> go co + go (TcLRCo lr co) = (pickLR lr . tcSplitAppTy) <$> go co -- c.f. Coercion.coercionKind go_inst (TcInstCo co ty) tys = go_inst co (ty:tys) @@ -239,6 +245,7 @@ coVarsOfTcCo tc_co go (TcSymCo co) = go co go (TcTransCo co1 co2) = go co1 `unionVarSet` go co2 go (TcNthCo _ co) = go co + go (TcLRCo _ co) = go co go (TcLetCo (EvBinds bs) co) = foldrBag (unionVarSet . go_bind) (go co) bs `minusVarSet` get_bndrs bs go (TcLetCo {}) = emptyVarSet -- Harumph. This does legitimately happen in the call @@ -306,6 +313,7 @@ ppr_co p (TcTransCo co1 co2) = maybeParen p FunPrec $ <+> ppr_co FunPrec co2 ppr_co p (TcSymCo co) = pprPrefixApp p (ptext (sLit "Sym")) [pprParendTcCo co] ppr_co p (TcNthCo n co) = pprPrefixApp p (ptext (sLit "Nth:") <+> int n) [pprParendTcCo co] +ppr_co p (TcLRCo lr co) = pprPrefixApp p (ppr lr) [pprParendTcCo co] ppr_fun_co :: Prec -> TcCoercion -> SDoc ppr_fun_co p co = pprArrowChain p (split co) diff --git a/compiler/typecheck/TcHsSyn.lhs b/compiler/typecheck/TcHsSyn.lhs index d56f7af1ac..ef53f4e24d 100644 --- a/compiler/typecheck/TcHsSyn.lhs +++ b/compiler/typecheck/TcHsSyn.lhs @@ -1357,6 +1357,7 @@ zonkTcLCoToLCo env co ; return (TcCastCo co1' co2') } go (TcSymCo co) = do { co' <- go co; return (mkTcSymCo co') } go (TcNthCo n co) = do { co' <- go co; return (mkTcNthCo n co') } + go (TcLRCo lr co) = do { co' <- go co; return (mkTcLRCo lr co') } go (TcTransCo co1 co2) = do { co1' <- go co1; co2' <- go co2 ; return (mkTcTransCo co1' co2') } go (TcForAllCo tv co) = ASSERT( isImmutableTyVar tv ) diff --git a/compiler/typecheck/TcType.lhs b/compiler/typecheck/TcType.lhs index 758573dd46..e129bac53c 100644 --- a/compiler/typecheck/TcType.lhs +++ b/compiler/typecheck/TcType.lhs @@ -662,6 +662,7 @@ tidyCo env@(_, subst) co go (SymCo co) = SymCo $! go co go (TransCo co1 co2) = (TransCo $! go co1) $! go co2 go (NthCo d co) = NthCo d $! go co + go (LRCo lr co) = LRCo lr $! go co go (InstCo co ty) = (InstCo $! go co) $! tidyType env ty tidyCos :: TidyEnv -> [Coercion] -> [Coercion] diff --git a/compiler/types/Coercion.lhs b/compiler/types/Coercion.lhs index 42e54ba47b..30e71fd563 100644 --- a/compiler/types/Coercion.lhs +++ b/compiler/types/Coercion.lhs @@ -17,6 +17,7 @@ module Coercion ( -- * Main data type Coercion(..), Var, CoVar, + LeftOrRight(..), pickLR, -- ** Functions over coercions coVarKind, @@ -31,7 +32,7 @@ module Coercion ( mkReflCo, mkCoVarCo, mkAxInstCo, mkAxInstRHS, mkPiCo, mkPiCos, mkCoCast, - mkSymCo, mkTransCo, mkNthCo, + mkSymCo, mkTransCo, mkNthCo, mkLRCo, mkInstCo, mkAppCo, mkTyConAppCo, mkFunCo, mkForAllCo, mkUnsafeCo, mkNewTypeCo, @@ -148,9 +149,17 @@ data Coercion | TransCo Coercion Coercion -- These are destructors - | NthCo Int Coercion -- Zero-indexed + | NthCo Int Coercion -- Zero-indexed; decomposes (T t0 ... tn) + | LRCo LeftOrRight Coercion -- Decomposes (t_left t_right) | InstCo Coercion Type deriving (Data.Data, Data.Typeable) + +data LeftOrRight = CLeft | CRight + deriving( Eq, Data.Data, Data.Typeable ) + +pickLR :: LeftOrRight -> (a,a) -> a +pickLR CLeft (l,_) = l +pickLR CRight (_,r) = r \end{code} @@ -337,6 +346,7 @@ tyCoVarsOfCo (UnsafeCo ty1 ty2) = tyVarsOfType ty1 `unionVarSet` tyVarsOfType t tyCoVarsOfCo (SymCo co) = tyCoVarsOfCo co tyCoVarsOfCo (TransCo co1 co2) = tyCoVarsOfCo co1 `unionVarSet` tyCoVarsOfCo co2 tyCoVarsOfCo (NthCo _ co) = tyCoVarsOfCo co +tyCoVarsOfCo (LRCo _ co) = tyCoVarsOfCo co tyCoVarsOfCo (InstCo co ty) = tyCoVarsOfCo co `unionVarSet` tyVarsOfType ty tyCoVarsOfCos :: [Coercion] -> VarSet @@ -354,6 +364,7 @@ coVarsOfCo (UnsafeCo _ _) = emptyVarSet coVarsOfCo (SymCo co) = coVarsOfCo co coVarsOfCo (TransCo co1 co2) = coVarsOfCo co1 `unionVarSet` coVarsOfCo co2 coVarsOfCo (NthCo _ co) = coVarsOfCo co +coVarsOfCo (LRCo _ co) = coVarsOfCo co coVarsOfCo (InstCo co _) = coVarsOfCo co coVarsOfCos :: [Coercion] -> VarSet @@ -370,6 +381,7 @@ coercionSize (UnsafeCo ty1 ty2) = typeSize ty1 + typeSize ty2 coercionSize (SymCo co) = 1 + coercionSize co coercionSize (TransCo co1 co2) = 1 + coercionSize co1 + coercionSize co2 coercionSize (NthCo _ co) = 1 + coercionSize co +coercionSize (LRCo _ co) = 1 + coercionSize co coercionSize (InstCo co ty) = 1 + coercionSize co + typeSize ty \end{code} @@ -416,8 +428,12 @@ ppr_co p (InstCo co ty) = maybeParen p TyConPrec $ ppr_co p (UnsafeCo ty1 ty2) = pprPrefixApp p (ptext (sLit "UnsafeCo")) [pprParendType ty1, pprParendType ty2] ppr_co p (SymCo co) = pprPrefixApp p (ptext (sLit "Sym")) [pprParendCo co] -ppr_co p (NthCo n co) = pprPrefixApp p (ptext (sLit "Nth:") <+> int n) [pprParendCo co] +ppr_co p (NthCo n co) = pprPrefixApp p (ptext (sLit "Nth:") <> int n) [pprParendCo co] +ppr_co p (LRCo sel co) = pprPrefixApp p (ppr sel) [pprParendCo co] +instance Outputable LeftOrRight where + ppr CLeft = ptext (sLit "Left") + ppr CRight = ptext (sLit "Right") ppr_fun_co :: Prec -> Coercion -> SDoc ppr_fun_co p co = pprArrowChain p (split co) @@ -625,6 +641,10 @@ mkNthCo n co = ASSERT( ok_tc_app _ty1 n && ok_tc_app _ty2 n ) where Pair _ty1 _ty2 = coercionKind co +mkLRCo :: LeftOrRight -> Coercion -> Coercion +mkLRCo lr (Refl ty) = Refl (pickLR lr (splitAppTy ty)) +mkLRCo lr co = LRCo lr co + ok_tc_app :: Type -> Int -> Bool ok_tc_app ty n = case splitTyConApp_maybe ty of Just (_, tys) -> tys `lengthExceeds` n @@ -759,6 +779,8 @@ coreEqCoercion2 env (TransCo co11 co12) (TransCo co21 co22) coreEqCoercion2 env (NthCo d1 co1) (NthCo d2 co2) = d1 == d2 && coreEqCoercion2 env co1 co2 +coreEqCoercion2 env (LRCo d1 co1) (LRCo d2 co2) + = d1 == d2 && coreEqCoercion2 env co1 co2 coreEqCoercion2 env (InstCo co1 ty1) (InstCo co2 ty2) = coreEqCoercion2 env co1 co2 && eqTypeX env ty1 ty2 @@ -900,6 +922,7 @@ subst_co subst co go (SymCo co) = mkSymCo (go co) go (TransCo co1 co2) = mkTransCo (go co1) (go co2) go (NthCo d co) = mkNthCo d (go co) + go (LRCo lr co) = mkLRCo lr (go co) go (InstCo co ty) = mkInstCo (go co) $! go_ty ty substCoVar :: CvSubst -> CoVar -> Coercion @@ -1073,6 +1096,7 @@ seqCo (UnsafeCo ty1 ty2) = seqType ty1 `seq` seqType ty2 seqCo (SymCo co) = seqCo co seqCo (TransCo co1 co2) = seqCo co1 `seq` seqCo co2 seqCo (NthCo _ co) = seqCo co +seqCo (LRCo _ co) = seqCo co seqCo (InstCo co ty) = seqCo co `seq` seqType ty seqCos :: [Coercion] -> () @@ -1114,6 +1138,7 @@ coercionKind co = go co go (SymCo co) = swap $ go co go (TransCo co1 co2) = Pair (pFst $ go co1) (pSnd $ go co2) go (NthCo d co) = tyConAppArgN d <$> go co + go (LRCo lr co) = (pickLR lr . splitAppTy) <$> go co go (InstCo aco ty) = go_app aco [ty] go_app :: Coercion -> [Type] -> Pair Type diff --git a/compiler/types/OptCoercion.lhs b/compiler/types/OptCoercion.lhs index 7d707c33c4..c699163e74 100644 --- a/compiler/types/OptCoercion.lhs +++ b/compiler/types/OptCoercion.lhs @@ -145,7 +145,7 @@ opt_co' env sym (TransCo co1 co2) opt_co' env sym (NthCo n co) | TyConAppCo tc cos <- co' - , isDecomposableTyCon tc -- Not synonym families + , isDecomposableTyCon tc -- Not synonym families = ASSERT( n < length cos ) cos !! n | otherwise @@ -153,6 +153,14 @@ opt_co' env sym (NthCo n co) where co' = opt_co env sym co +opt_co' env sym (LRCo lr co) + | Just pr_co <- splitAppCo_maybe co' + = pickLR lr pr_co + | otherwise + = LRCo lr co' + where + co' = opt_co env sym co + opt_co' env sym (InstCo co ty) -- See if the first arg is already a forall -- ...then we can just extend the current substitution @@ -165,7 +173,6 @@ opt_co' env sym (InstCo co ty) = substCoWithTy (getCvInScope env) tv ty' co'_body | otherwise = InstCo co' ty' - where co' = opt_co env sym co ty' = substTy env ty @@ -208,18 +215,19 @@ opt_trans2 _ co1 co2 -- Optimize coercions with a top-level use of transitivity. opt_trans_rule :: InScopeSet -> NormalNonIdCo -> NormalNonIdCo -> Maybe NormalCo --- push transitivity down through matching top-level constructors. -opt_trans_rule is in_co1@(TyConAppCo tc1 cos1) in_co2@(TyConAppCo tc2 cos2) - | tc1 == tc2 = fireTransRule "PushTyConApp" in_co1 in_co2 $ - TyConAppCo tc1 (opt_transList is cos1 cos2) - --- push transitivity through matching destructors +-- Push transitivity through matching destructors opt_trans_rule is in_co1@(NthCo d1 co1) in_co2@(NthCo d2 co2) | d1 == d2 , co1 `compatible_co` co2 = fireTransRule "PushNth" in_co1 in_co2 $ mkNthCo d1 (opt_trans is co1 co2) +opt_trans_rule is in_co1@(LRCo d1 co1) in_co2@(LRCo d2 co2) + | d1 == d2 + , co1 `compatible_co` co2 + = fireTransRule "PushLR" in_co1 in_co2 $ + mkLRCo d1 (opt_trans is co1 co2) + -- Push transitivity inside instantiation opt_trans_rule is in_co1@(InstCo co1 ty1) in_co2@(InstCo co2 ty2) | ty1 `eqType` ty2 @@ -227,11 +235,17 @@ opt_trans_rule is in_co1@(InstCo co1 ty1) in_co2@(InstCo co2 ty2) = fireTransRule "TrPushInst" in_co1 in_co2 $ mkInstCo (opt_trans is co1 co2) ty1 --- Push transitivity inside apply +-- Push transitivity down through matching top-level constructors. +opt_trans_rule is in_co1@(TyConAppCo tc1 cos1) in_co2@(TyConAppCo tc2 cos2) + | tc1 == tc2 + = fireTransRule "PushTyConApp" in_co1 in_co2 $ + TyConAppCo tc1 (opt_transList is cos1 cos2) + opt_trans_rule is in_co1@(AppCo co1a co1b) in_co2@(AppCo co2a co2b) = fireTransRule "TrPushApp" in_co1 in_co2 $ mkAppCo (opt_trans is co1a co2a) (opt_trans is co1b co2b) +-- Eta rules opt_trans_rule is co1@(TyConAppCo tc cos1) co2 | Just cos2 <- etaTyConAppCo_maybe tc co2 = ASSERT( length cos1 == length cos2 ) @@ -244,6 +258,16 @@ opt_trans_rule is co1 co2@(TyConAppCo tc cos2) fireTransRule "EtaCompR" co1 co2 $ TyConAppCo tc (opt_transList is cos1 cos2) +opt_trans_rule is co1@(AppCo co1a co1b) co2 + | Just (co2a,co2b) <- etaAppCo_maybe co2 + = fireTransRule "EtaAppL" co1 co2 $ + mkAppCo (opt_trans is co1a co2a) (opt_trans is co1b co2b) + +opt_trans_rule is co1 co2@(AppCo co2a co2b) + | Just (co1a,co1b) <- etaAppCo_maybe co1 + = fireTransRule "EtaAppR" co1 co2 $ + mkAppCo (opt_trans is co1a co2a) (opt_trans is co1b co2b) + -- Push transitivity inside forall opt_trans_rule is co1 co2 | Just (tv1,r1) <- splitForAllCo_maybe co1 @@ -359,6 +383,20 @@ etaForAllCo_maybe co | otherwise = Nothing +etaAppCo_maybe :: Coercion -> Maybe (Coercion,Coercion) +-- If possible, split a coercion +-- g :: t1a t1b ~ t2a t2b +-- into a pair of coercions (left g, right g) +etaAppCo_maybe co + | Just (co1,co2) <- splitAppCo_maybe co + = Just (co1,co2) + | Pair ty1 ty2 <- coercionKind co + , Just {} <- splitAppTy_maybe ty1 + , Just {} <- splitAppTy_maybe ty2 + = Just (LRCo CLeft co, LRCo CRight co) + | otherwise + = Nothing + etaTyConAppCo_maybe :: TyCon -> Coercion -> Maybe [Coercion] -- If possible, split a coercion -- g :: T s1 .. sn ~ T t1 .. tn |