summaryrefslogtreecommitdiff
path: root/compiler/typecheck/TcEvidence.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/typecheck/TcEvidence.hs')
-rw-r--r--compiler/typecheck/TcEvidence.hs663
1 files changed, 142 insertions, 521 deletions
diff --git a/compiler/typecheck/TcEvidence.hs b/compiler/typecheck/TcEvidence.hs
index 18f162256d..032cc54730 100644
--- a/compiler/typecheck/TcEvidence.hs
+++ b/compiler/typecheck/TcEvidence.hs
@@ -13,50 +13,50 @@ module TcEvidence (
-- Evidence bindings
TcEvBinds(..), EvBindsVar(..),
EvBindMap(..), emptyEvBindMap, extendEvBinds,
- lookupEvBind, evBindMapBinds, foldEvBindMap,
+ lookupEvBind, evBindMapBinds, foldEvBindMap,
EvBind(..), emptyTcEvBinds, isEmptyTcEvBinds, mkGivenEvBind, mkWantedEvBind,
+ sccEvBinds, evBindVar,
EvTerm(..), mkEvCast, evVarsOfTerm, mkEvScSelectors,
EvLit(..), evTermCoercion,
EvCallStack(..),
EvTypeable(..),
-- TcCoercion
- TcCoercion(..), TcCoercionR, TcCoercionN,
- LeftOrRight(..), pickLR,
+ TcCoercion, TcCoercionR, TcCoercionN, TcCoercionP, CoercionHole,
+ Role(..), LeftOrRight(..), pickLR,
mkTcReflCo, mkTcNomReflCo, mkTcRepReflCo,
- mkTcTyConAppCo, mkTcAppCo, mkTcAppCos, mkTcFunCo,
+ mkTcTyConAppCo, mkTcAppCo, mkTcFunCo,
mkTcAxInstCo, mkTcUnbranchedAxInstCo, mkTcForAllCo, mkTcForAllCos,
mkTcSymCo, mkTcTransCo, mkTcNthCo, mkTcLRCo, mkTcSubCo, maybeTcSubCo,
- tcDowngradeRole, mkTcTransAppCo,
- mkTcAxiomRuleCo, mkTcPhantomCo,
- tcCoercionKind, coVarsOfTcCo, isEqVar, mkTcCoVarCo,
- isTcReflCo, getTcCoVar_maybe,
- tcCoercionRole, eqVarRole,
+ tcDowngradeRole,
+ mkTcAxiomRuleCo, mkTcCoherenceLeftCo, mkTcCoherenceRightCo, mkTcPhantomCo,
+ mkTcKindCo,
+ tcCoercionKind, coVarsOfTcCo,
+ mkTcCoVarCo,
+ isTcReflCo,
+ tcCoercionRole,
unwrapIP, wrapIP
) where
#include "HsVersions.h"
import Var
+import CoAxiom
import Coercion
import PprCore () -- Instance OutputableBndr TyVar
-import TypeRep -- Knows type representation
import TcType
import Type
import TyCon
import Class( Class )
-import CoAxiom
import PrelNames
+import DynFlags ( gopt, GeneralFlag(Opt_PrintExplicitCoercions) )
import VarEnv
import VarSet
import Name
+import Pair
import Util
import Bag
-import Pair
-#if __GLASGOW_HASKELL__ < 709
-import Control.Applicative
-import Data.Traversable (traverse, sequenceA)
-#endif
+import Digraph
import qualified Data.Data as Data
import Outputable
import FastString
@@ -71,483 +71,82 @@ Coercions have free variables of type (a ~# b): we call these
CoVars. However, the type checker passes around equality evidence
(boxed up) at type (a ~ b).
-An TcCoercion is simply a Coercion whose free variables have the
-boxed type (a ~ b). After we are done with typechecking the
-desugarer finds the free variables, unboxes them, and creates a
-resulting real Coercion with kosher free variables.
-
-We can use most of the Coercion "smart constructors" to build TcCoercions.
-However, mkCoVarCo will not work! The equivalent is mkTcCoVarCo.
-
-The data type is similar to Coercion.Coercion, with the following
-differences
- * Most important, TcLetCo adds let-bindings for coercions.
- This is what lets us unify two for-all types and generate
- equality constraints underneath
-
- * The kind of a TcCoercion is t1 ~ t2 (resp. Coercible t1 t2)
- of a Coercion is t1 ~# t2 (resp. t1 ~#R t2)
-
- * UnsafeCo aren't required, but we do have TcPhantomCo
-
- * Representation invariants are weaker:
- - we are allowed to have type synonyms in TcTyConAppCo
- - the first arg of a TcAppCo can be a TcTyConAppCo
- - TcSubCo is not applied as deep as done with mkSubCo
- Reason: they'll get established when we desugar to Coercion
-
- * TcAxiomInstCo has a [TcCoercion] parameter, and not a [Type] parameter.
- This differs from the formalism, but corresponds to AxiomInstCo (see
- [Coercion axioms applied to coercions]).
-
-Note [mkTcTransAppCo]
-~~~~~~~~~~~~~~~~~~~~~
-Suppose we have
-
- co1 :: a ~R Maybe
- co2 :: b ~R Int
-
-and we want
-
- co3 :: a b ~R Maybe Int
-
-This seems sensible enough. But, we can't let (co3 = co1 co2), because
-that's ill-roled! Note that mkTcAppCo requires a *nominal* second coercion.
-
-The way around this is to use transitivity:
-
- co3 = (co1 <b>_N) ; (Maybe co2) :: a b ~R Maybe Int
-
-Or, it's possible everything is the other way around:
-
- co1' :: Maybe ~R a
- co2' :: Int ~R b
-
-and we want
+An TcCoercion is simply a Coercion whose free variables have may be either
+boxed or unboxed. After we are done with typechecking the desugarer finds the
+boxed free variables, unboxes them, and creates a resulting real Coercion with
+kosher free variables.
- co3' :: Maybe Int ~R a b
-
-then
-
- co3' = (Maybe co2') ; (co1' <b>_N)
-
-This is exactly what `mkTcTransAppCo` builds for us. Information for all
-the arguments tends to be to hand at call sites, so it's quicker than
-using, say, tcCoercionKind.
-}
-type TcCoercionN = TcCoercion -- A Nominal corecion ~N
-type TcCoercionR = TcCoercion -- A Representational corecion ~R
-
-data TcCoercion
- = TcRefl Role TcType
- | TcTyConAppCo Role TyCon [TcCoercion]
- | TcAppCo TcCoercion TcCoercion
- | TcForAllCo TyVar TcCoercion
- | TcCoVarCo EqVar
- | TcAxiomInstCo (CoAxiom Branched) Int -- Int specifies branch number
- [TcCoercion] -- See [CoAxiom Index] in Coercion.hs
- -- This is number of types and coercions are expected to match to CoAxiomRule
- -- (i.e., the CoAxiomRules are always fully saturated)
- | TcAxiomRuleCo CoAxiomRule [TcType] [TcCoercion]
- | TcPhantomCo TcType TcType
- | TcSymCo TcCoercion
- | TcTransCo TcCoercion TcCoercion
- | TcNthCo Int TcCoercion
- | TcLRCo LeftOrRight TcCoercion
- | TcSubCo TcCoercion -- Argument is never TcRefl
- | TcCastCo TcCoercion TcCoercion -- co1 |> co2
- | TcLetCo TcEvBinds TcCoercion
- | TcCoercion Coercion -- embed a Core Coercion
- deriving (Data.Data, Data.Typeable)
+type TcCoercion = Coercion
+type TcCoercionN = CoercionN -- A Nominal corecion ~N
+type TcCoercionR = CoercionR -- A Representational corecion ~R
+type TcCoercionP = CoercionP -- a phantom coercion
+
+mkTcReflCo :: Role -> TcType -> TcCoercion
+mkTcSymCo :: TcCoercion -> TcCoercion
+mkTcTransCo :: TcCoercion -> TcCoercion -> TcCoercion
+mkTcNomReflCo :: TcType -> TcCoercionN
+mkTcRepReflCo :: TcType -> TcCoercionR
+mkTcTyConAppCo :: Role -> TyCon -> [TcCoercion] -> TcCoercion
+mkTcAppCo :: TcCoercion -> TcCoercionN -> TcCoercion
+mkTcFunCo :: Role -> TcCoercion -> TcCoercion -> TcCoercion
+mkTcAxInstCo :: Role -> CoAxiom br -> BranchIndex
+ -> [TcType] -> [TcCoercion] -> TcCoercion
+mkTcUnbranchedAxInstCo :: CoAxiom Unbranched -> [TcType]
+ -> [TcCoercion] -> TcCoercionR
+mkTcForAllCo :: TyVar -> TcCoercionN -> TcCoercion -> TcCoercion
+mkTcForAllCos :: [(TyVar, TcCoercionN)] -> TcCoercion -> TcCoercion
+mkTcNthCo :: Int -> TcCoercion -> TcCoercion
+mkTcLRCo :: LeftOrRight -> TcCoercion -> TcCoercion
+mkTcSubCo :: TcCoercionN -> TcCoercionR
+maybeTcSubCo :: EqRel -> TcCoercion -> TcCoercion
+tcDowngradeRole :: Role -> Role -> TcCoercion -> TcCoercion
+mkTcAxiomRuleCo :: CoAxiomRule -> [TcCoercion] -> TcCoercionR
+mkTcCoherenceLeftCo :: TcCoercion -> TcCoercionN -> TcCoercion
+mkTcCoherenceRightCo :: TcCoercion -> TcCoercionN -> TcCoercion
+mkTcPhantomCo :: TcCoercionN -> TcType -> TcType -> TcCoercionP
+mkTcKindCo :: TcCoercion -> TcCoercionN
+mkTcCoVarCo :: CoVar -> TcCoercion
+
+tcCoercionKind :: TcCoercion -> Pair TcType
+tcCoercionRole :: TcCoercion -> Role
+coVarsOfTcCo :: TcCoercion -> TcTyCoVarSet
+isTcReflCo :: TcCoercion -> Bool
+
+mkTcReflCo = mkReflCo
+mkTcSymCo = mkSymCo
+mkTcTransCo = mkTransCo
+mkTcNomReflCo = mkNomReflCo
+mkTcRepReflCo = mkRepReflCo
+mkTcTyConAppCo = mkTyConAppCo
+mkTcAppCo = mkAppCo
+mkTcFunCo = mkFunCo
+mkTcAxInstCo = mkAxInstCo
+mkTcUnbranchedAxInstCo = mkUnbranchedAxInstCo Representational
+mkTcForAllCo = mkForAllCo
+mkTcForAllCos = mkForAllCos
+mkTcNthCo = mkNthCo
+mkTcLRCo = mkLRCo
+mkTcSubCo = mkSubCo
+maybeTcSubCo = maybeSubCo
+tcDowngradeRole = downgradeRole
+mkTcAxiomRuleCo = mkAxiomRuleCo
+mkTcCoherenceLeftCo = mkCoherenceLeftCo
+mkTcCoherenceRightCo = mkCoherenceRightCo
+mkTcPhantomCo = mkPhantomCo
+mkTcKindCo = mkKindCo
+mkTcCoVarCo = mkCoVarCo
+
+tcCoercionKind = coercionKind
+tcCoercionRole = coercionRole
+coVarsOfTcCo = coVarsOfCo
+isTcReflCo = isReflCo
-isEqVar :: Var -> Bool
--- Is lifted coercion variable (only!)
-isEqVar v = case tyConAppTyCon_maybe (varType v) of
- Just tc -> tc `hasKey` eqTyConKey
- Nothing -> False
-
-isTcReflCo_maybe :: TcCoercion -> Maybe TcType
-isTcReflCo_maybe (TcRefl _ ty) = Just ty
-isTcReflCo_maybe (TcCoercion co) = isReflCo_maybe co
-isTcReflCo_maybe _ = Nothing
-
-isTcReflCo :: TcCoercion -> Bool
-isTcReflCo (TcRefl {}) = True
-isTcReflCo (TcCoercion co) = isReflCo co
-isTcReflCo _ = False
-
-getTcCoVar_maybe :: TcCoercion -> Maybe CoVar
-getTcCoVar_maybe (TcCoVarCo v) = Just v
-getTcCoVar_maybe _ = Nothing
-
-mkTcReflCo :: Role -> TcType -> TcCoercion
-mkTcReflCo = TcRefl
-
-mkTcNomReflCo :: TcType -> TcCoercion
-mkTcNomReflCo = TcRefl Nominal
-
-mkTcRepReflCo :: TcType -> TcCoercion
-mkTcRepReflCo = TcRefl Representational
-
-mkTcFunCo :: Role -> TcCoercion -> TcCoercion -> TcCoercion
-mkTcFunCo role co1 co2 = mkTcTyConAppCo role funTyCon [co1, co2]
-
-mkTcTyConAppCo :: Role -> TyCon -> [TcCoercion] -> TcCoercion
-mkTcTyConAppCo role tc cos -- No need to expand type synonyms
- -- See Note [TcCoercions]
- | Just tys <- traverse isTcReflCo_maybe cos
- = TcRefl role (mkTyConApp tc tys) -- See Note [Refl invariant]
-
- | otherwise = TcTyConAppCo role tc cos
-
--- Input coercion is Nominal
--- mkSubCo will do some normalisation. We do not do it for TcCoercions, but
--- defer that to desugaring; just to reduce the code duplication a little bit
-mkTcSubCo :: TcCoercionN -> TcCoercionR
-mkTcSubCo (TcRefl _ ty)
- = TcRefl Representational ty
-mkTcSubCo co
- = ASSERT2( tcCoercionRole co == Nominal, ppr co)
- TcSubCo co
-
--- See Note [Role twiddling functions] in Coercion
--- | Change the role of a 'TcCoercion'. Returns 'Nothing' if this isn't
--- a downgrade.
-tcDowngradeRole_maybe :: Role -- desired role
- -> Role -- current role
- -> TcCoercion -> Maybe TcCoercion
-tcDowngradeRole_maybe Representational Nominal = Just . mkTcSubCo
-tcDowngradeRole_maybe Nominal Representational = const Nothing
-tcDowngradeRole_maybe Phantom _
- = panic "tcDowngradeRole_maybe Phantom"
- -- not supported (not needed at the moment)
-tcDowngradeRole_maybe _ Phantom = const Nothing
-tcDowngradeRole_maybe _ _ = Just
-
--- See Note [Role twiddling functions] in Coercion
--- | Change the role of a 'TcCoercion'. Panics if this isn't a downgrade.
-tcDowngradeRole :: Role -- ^ desired role
- -> Role -- ^ current role
- -> TcCoercion -> TcCoercion
-tcDowngradeRole r1 r2 co
- = case tcDowngradeRole_maybe r1 r2 co of
- Just co' -> co'
- Nothing -> pprPanic "tcDowngradeRole" (ppr r1 <+> ppr r2 <+> ppr co)
-
--- | If the EqRel is ReprEq, makes a TcSubCo; otherwise, does nothing.
--- Note that the input coercion should always be nominal.
-maybeTcSubCo :: EqRel -> TcCoercion -> TcCoercion
-maybeTcSubCo NomEq = id
-maybeTcSubCo ReprEq = mkTcSubCo
-
-mkTcAxInstCo :: Role -> CoAxiom br -> Int -> [TcType] -> TcCoercion
-mkTcAxInstCo role ax index tys
- | ASSERT2( not (role == Nominal && ax_role == Representational) , ppr (ax, tys) )
- arity == n_tys = tcDowngradeRole role ax_role $
- TcAxiomInstCo ax_br index rtys
- | otherwise = ASSERT( arity < n_tys )
- tcDowngradeRole role ax_role $
- foldl TcAppCo (TcAxiomInstCo ax_br index (take arity rtys))
- (drop arity rtys)
- where
- n_tys = length tys
- ax_br = toBranchedAxiom ax
- branch = coAxiomNthBranch ax_br index
- arity = length $ coAxBranchTyVars branch
- ax_role = coAxiomRole ax
- arg_roles = coAxBranchRoles branch
- rtys = zipWith mkTcReflCo (arg_roles ++ repeat Nominal) tys
-
-mkTcAxiomRuleCo :: CoAxiomRule -> [TcType] -> [TcCoercion] -> TcCoercionR
-mkTcAxiomRuleCo = TcAxiomRuleCo
-
-mkTcUnbranchedAxInstCo :: CoAxiom Unbranched -> [TcType] -> TcCoercionR
-mkTcUnbranchedAxInstCo ax tys = mkTcAxInstCo Representational ax 0 tys
-
-mkTcAppCo :: TcCoercion -> TcCoercion -> TcCoercion
--- No need to deal with TyConApp on the left; see Note [TcCoercions]
--- Second coercion *must* be nominal
-mkTcAppCo (TcRefl r ty1) (TcRefl _ ty2) = TcRefl r (mkAppTy ty1 ty2)
-mkTcAppCo co1 co2 = TcAppCo co1 co2
-
--- | Like `mkTcAppCo`, but allows the second coercion to be other than
--- nominal. See Note [mkTcTransAppCo]. Role r3 cannot be more stringent
--- than either r1 or r2.
-mkTcTransAppCo :: Role -- ^ r1
- -> TcCoercion -- ^ co1 :: ty1a ~r1 ty1b
- -> TcType -- ^ ty1a
- -> TcType -- ^ ty1b
- -> Role -- ^ r2
- -> TcCoercion -- ^ co2 :: ty2a ~r2 ty2b
- -> TcType -- ^ ty2a
- -> TcType -- ^ ty2b
- -> Role -- ^ r3
- -> TcCoercion -- ^ :: ty1a ty2a ~r3 ty1b ty2b
-mkTcTransAppCo r1 co1 ty1a ty1b r2 co2 ty2a ty2b r3
--- How incredibly fiddly! Is there a better way??
- = case (r1, r2, r3) of
- (_, _, Phantom)
- -> mkTcPhantomCo (mkAppTy ty1a ty2a) (mkAppTy ty1b ty2b)
- (_, _, Nominal)
- -> ASSERT( r1 == Nominal && r2 == Nominal )
- mkTcAppCo co1 co2
- (Nominal, Nominal, Representational)
- -> mkTcSubCo (mkTcAppCo co1 co2)
- (_, Nominal, Representational)
- -> ASSERT( r1 == Representational )
- mkTcAppCo co1 co2
- (Nominal, Representational, Representational)
- -> go (mkTcSubCo co1)
- (_ , _, Representational)
- -> ASSERT( r1 == Representational && r2 == Representational )
- go co1
- where
- go co1_repr
- | Just (tc1b, tys1b) <- tcSplitTyConApp_maybe ty1b
- , nextRole ty1b == r2
- = (co1_repr `mkTcAppCo` mkTcNomReflCo ty2a) `mkTcTransCo`
- (mkTcTyConAppCo Representational tc1b
- (zipWith mkTcReflCo (tyConRolesX Representational tc1b) tys1b
- ++ [co2]))
-
- | Just (tc1a, tys1a) <- tcSplitTyConApp_maybe ty1a
- , nextRole ty1a == r2
- = (mkTcTyConAppCo Representational tc1a
- (zipWith mkTcReflCo (tyConRolesX Representational tc1a) tys1a
- ++ [co2]))
- `mkTcTransCo`
- (co1_repr `mkTcAppCo` mkTcNomReflCo ty2b)
-
- | otherwise
- = pprPanic "mkTcTransAppCo" (vcat [ ppr r1, ppr co1, ppr ty1a, ppr ty1b
- , ppr r2, ppr co2, ppr ty2a, ppr ty2b
- , ppr r3 ])
-
-mkTcSymCo :: TcCoercion -> TcCoercion
-mkTcSymCo co@(TcRefl {}) = co
-mkTcSymCo (TcSymCo co) = co
-mkTcSymCo co = TcSymCo co
-
-mkTcTransCo :: TcCoercion -> TcCoercion -> TcCoercion
-mkTcTransCo (TcRefl {}) co = co
-mkTcTransCo co (TcRefl {}) = co
-mkTcTransCo co1 co2 = TcTransCo co1 co2
-
-mkTcNthCo :: Int -> TcCoercion -> TcCoercion
-mkTcNthCo n (TcRefl r ty) = TcRefl r (tyConAppArgN n ty)
-mkTcNthCo n co = TcNthCo n co
-
-mkTcLRCo :: LeftOrRight -> TcCoercion -> TcCoercion
-mkTcLRCo lr (TcRefl r ty) = TcRefl r (pickLR lr (tcSplitAppTy ty))
-mkTcLRCo lr co = TcLRCo lr co
-
-mkTcPhantomCo :: TcType -> TcType -> TcCoercion
-mkTcPhantomCo = TcPhantomCo
-
-mkTcAppCos :: TcCoercion -> [TcCoercion] -> TcCoercion
-mkTcAppCos co1 tys = foldl mkTcAppCo co1 tys
-
-mkTcForAllCo :: Var -> TcCoercion -> TcCoercion
--- note that a TyVar should be used here, not a CoVar (nor a TcTyVar)
-mkTcForAllCo tv (TcRefl r ty) = ASSERT( isTyVar tv ) TcRefl r (mkForAllTy tv ty)
-mkTcForAllCo tv co = ASSERT( isTyVar tv ) TcForAllCo tv co
-
-mkTcForAllCos :: [Var] -> TcCoercion -> TcCoercion
-mkTcForAllCos tvs (TcRefl r ty) = ASSERT( all isTyVar tvs ) TcRefl r (mkForAllTys tvs ty)
-mkTcForAllCos tvs co = ASSERT( all isTyVar tvs ) foldr TcForAllCo co tvs
-
-mkTcCoVarCo :: EqVar -> TcCoercion
--- ipv :: s ~ t (the boxed equality type) or Coercible s t (the boxed representational equality type)
-mkTcCoVarCo ipv = TcCoVarCo ipv
- -- Previously I checked for (ty ~ ty) and generated Refl,
- -- but in fact ipv may not even (visibly) have a (t1 ~ t2) type, because
- -- the constraint solver does not substitute in the types of
- -- evidence variables as it goes. In any case, the optimisation
- -- will be done in the later zonking phase
-
-tcCoercionKind :: TcCoercion -> Pair Type
-tcCoercionKind co = go co
- where
- go (TcRefl _ ty) = Pair ty ty
- go (TcLetCo _ co) = go co
- go (TcCastCo _ co) = case getEqPredTys (pSnd (go co)) of
- (ty1,ty2) -> Pair ty1 ty2
- go (TcTyConAppCo _ tc cos)= mkTyConApp tc <$> (sequenceA $ map go cos)
- go (TcAppCo co1 co2) = mkAppTy <$> go co1 <*> go co2
- go (TcForAllCo tv co) = mkForAllTy tv <$> go co
- go (TcCoVarCo cv) = eqVarKind cv
- go (TcAxiomInstCo ax ind cos)
- = let branch = coAxiomNthBranch ax ind
- tvs = coAxBranchTyVars branch
- Pair tys1 tys2 = sequenceA (map go cos)
- in ASSERT( cos `equalLength` tvs )
- Pair (substTyWith tvs tys1 (coAxNthLHS ax ind))
- (substTyWith tvs tys2 (coAxBranchRHS branch))
- go (TcPhantomCo ty1 ty2) = Pair ty1 ty2
- 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
- go (TcSubCo co) = go co
- go (TcAxiomRuleCo ax ts cs) =
- case coaxrProves ax ts (map tcCoercionKind cs) of
- Just res -> res
- Nothing -> panic "tcCoercionKind: malformed TcAxiomRuleCo"
- go (TcCoercion co) = coercionKind co
-
-eqVarRole :: EqVar -> Role
-eqVarRole cv = getEqPredRole (varType cv)
-
-eqVarKind :: EqVar -> Pair Type
-eqVarKind cv
- | Just (tc, [_kind,ty1,ty2]) <- tcSplitTyConApp_maybe (varType cv)
- = ASSERT(tc `hasKey` eqTyConKey)
- Pair ty1 ty2
- | otherwise = pprPanic "eqVarKind, non coercion variable" (ppr cv <+> dcolon <+> ppr (varType cv))
-
-tcCoercionRole :: TcCoercion -> Role
-tcCoercionRole = go
- where
- go (TcRefl r _) = r
- go (TcTyConAppCo r _ _) = r
- go (TcAppCo co _) = go co
- go (TcForAllCo _ co) = go co
- go (TcCoVarCo cv) = eqVarRole cv
- go (TcAxiomInstCo ax _ _) = coAxiomRole ax
- go (TcPhantomCo _ _) = Phantom
- go (TcSymCo co) = go co
- go (TcTransCo co1 _) = go co1 -- same as go co2
- go (TcNthCo n co) = let Pair ty1 _ = tcCoercionKind co
- (tc, _) = tcSplitTyConApp ty1
- in nthRole (go co) tc n
- go (TcLRCo _ _) = Nominal
- go (TcSubCo _) = Representational
- go (TcAxiomRuleCo c _ _) = coaxrRole c
- go (TcCastCo c _) = go c
- go (TcLetCo _ c) = go c
- go (TcCoercion co) = coercionRole co
-
-
-coVarsOfTcCo :: TcCoercion -> VarSet
--- Only works on *zonked* coercions, because of TcLetCo
-coVarsOfTcCo tc_co
- = go tc_co
- where
- go (TcRefl _ _) = emptyVarSet
- go (TcTyConAppCo _ _ cos) = mapUnionVarSet go cos
- go (TcAppCo co1 co2) = go co1 `unionVarSet` go co2
- go (TcCastCo co1 co2) = go co1 `unionVarSet` go co2
- go (TcForAllCo _ co) = go co
- go (TcCoVarCo v) = unitVarSet v
- go (TcAxiomInstCo _ _ cos) = mapUnionVarSet go cos
- go (TcPhantomCo _ _) = emptyVarSet
- 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 (TcSubCo 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
- -- to evVarsOfTerm in the DEBUG check of setEvBind
- go (TcAxiomRuleCo _ _ cos) = mapUnionVarSet go cos
- go (TcCoercion co) = -- the use of coVarsOfTcCo in dsTcCoercion will
- -- fail if there are any proper, unlifted covars
- ASSERT( isEmptyVarSet (coVarsOfCo co) )
- emptyVarSet
-
- -- We expect only coercion bindings, so use evTermCoercion
- go_bind :: EvBind -> VarSet
- go_bind (EvBind { eb_rhs =tm }) = go (evTermCoercion tm)
-
- get_bndrs :: Bag EvBind -> VarSet
- get_bndrs = foldrBag (\ (EvBind { eb_lhs = b }) bs -> extendVarSet bs b) emptyVarSet
-
--- Pretty printing
-
-instance Outputable TcCoercion where
- ppr = pprTcCo
-
-pprTcCo, pprParendTcCo :: TcCoercion -> SDoc
-pprTcCo co = ppr_co TopPrec co
-pprParendTcCo co = ppr_co TyConPrec co
-
-ppr_co :: TyPrec -> TcCoercion -> SDoc
-ppr_co _ (TcRefl r ty) = angleBrackets (ppr ty) <> ppr_role r
-
-ppr_co p co@(TcTyConAppCo _ tc [_,_])
- | tc `hasKey` funTyConKey = ppr_fun_co p co
-
-ppr_co p (TcTyConAppCo r tc cos) = pprTcApp p ppr_co tc cos <> ppr_role r
-ppr_co p (TcLetCo bs co) = maybeParen p TopPrec $
- sep [ptext (sLit "let") <+> braces (ppr bs), ppr co]
-ppr_co p (TcAppCo co1 co2) = maybeParen p TyConPrec $
- pprTcCo co1 <+> ppr_co TyConPrec co2
-ppr_co p (TcCastCo co1 co2) = maybeParen p FunPrec $
- ppr_co FunPrec co1 <+> ptext (sLit "|>") <+> ppr_co FunPrec co2
-ppr_co p co@(TcForAllCo {}) = ppr_forall_co p co
-
-ppr_co _ (TcCoVarCo cv) = parenSymOcc (getOccName cv) (ppr cv)
-
-ppr_co p (TcAxiomInstCo con ind cos)
- = pprPrefixApp p (ppr (getName con) <> brackets (ppr ind)) (map pprParendTcCo cos)
-
-ppr_co p (TcTransCo co1 co2) = maybeParen p FunPrec $
- ppr_co FunPrec co1
- <+> ptext (sLit ";")
- <+> ppr_co FunPrec co2
-ppr_co p (TcPhantomCo t1 t2) = pprPrefixApp p (ptext (sLit "PhantomCo")) [pprParendType t1, pprParendType t2]
-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_co p (TcSubCo co) = pprPrefixApp p (ptext (sLit "Sub")) [pprParendTcCo co]
-ppr_co p (TcAxiomRuleCo co ts ps) = maybeParen p TopPrec
- $ ppr_tc_axiom_rule_co co ts ps
-ppr_co p (TcCoercion co) = pprPrefixApp p (text "Core co:") [ppr co]
-
-ppr_tc_axiom_rule_co :: CoAxiomRule -> [TcType] -> [TcCoercion] -> SDoc
-ppr_tc_axiom_rule_co co ts ps = ppr (coaxrName co) <> ppTs ts $$ nest 2 (ppPs ps)
- where
- ppTs [] = Outputable.empty
- ppTs [t] = ptext (sLit "@") <> ppr_type TopPrec t
- ppTs ts = ptext (sLit "@") <>
- parens (hsep $ punctuate comma $ map pprType ts)
-
- ppPs [] = Outputable.empty
- ppPs [p] = pprParendTcCo p
- ppPs (p : ps) = ptext (sLit "(") <+> pprTcCo p $$
- vcat [ ptext (sLit ",") <+> pprTcCo q | q <- ps ] $$
- ptext (sLit ")")
-
-ppr_role :: Role -> SDoc
-ppr_role r = underscore <> pp_role
- where pp_role = case r of
- Nominal -> char 'N'
- Representational -> char 'R'
- Phantom -> char 'P'
-
-ppr_fun_co :: TyPrec -> TcCoercion -> SDoc
-ppr_fun_co p co = pprArrowChain p (split co)
- where
- split :: TcCoercion -> [SDoc]
- split (TcTyConAppCo _ f [arg,res])
- | f `hasKey` funTyConKey
- = ppr_co FunPrec arg : split res
- split co = [ppr_co TopPrec co]
-
-ppr_forall_co :: TyPrec -> TcCoercion -> SDoc
-ppr_forall_co p ty
- = maybeParen p FunPrec $
- sep [pprForAll tvs, ppr_co TopPrec rho]
- where
- (tvs, rho) = split1 [] ty
- split1 tvs (TcForAllCo tv ty) = split1 (tv:tvs) ty
- split1 tvs ty = (reverse tvs, ty)
{-
-************************************************************************
-* *
+%************************************************************************
+%* *
HsWrapper
* *
************************************************************************
@@ -567,7 +166,7 @@ data HsWrapper
-- So note that if wrap1 :: exp_arg <= act_arg
-- wrap2 :: act_res <= exp_res
-- then WpFun wrap1 wrap2 : (act_arg -> arg_res) <= (exp_arg -> exp_res)
- -- This isn't the same as for mkTcFunCo, but it has to be this way
+ -- This isn't the same as for mkFunCo, but it has to be this way
-- because we can't use 'sym' to flip around these HsWrappers
| WpCast TcCoercionR -- A cast: [] `cast` co
@@ -576,9 +175,8 @@ data HsWrapper
-- Evidence abstraction and application
-- (both dictionaries and coercions)
- | WpEvLam EvVar -- \d. [] the 'd' is an evidence variable
- | WpEvApp EvTerm -- [] d the 'd' is evidence for a constraint
-
+ | WpEvLam EvVar -- \d. [] the 'd' is an evidence variable
+ | WpEvApp EvTerm -- [] d the 'd' is evidence for a constraint
-- Kind and Type abstraction and application
| WpTyLam TyVar -- \a. [] the 'a' is a type/kind variable (not coercion var)
| WpTyApp KindOrType -- [] t the 't' is a type (not coercion)
@@ -596,9 +194,9 @@ c1 <.> c2 = c1 `WpCompose` c2
mkWpFun :: HsWrapper -> HsWrapper -> TcType -> TcType -> HsWrapper
mkWpFun WpHole WpHole _ _ = WpHole
-mkWpFun WpHole (WpCast co2) t1 _ = WpCast (mkTcFunCo Representational (mkTcRepReflCo t1) co2)
-mkWpFun (WpCast co1) WpHole _ t2 = WpCast (mkTcFunCo Representational (mkTcSymCo co1) (mkTcRepReflCo t2))
-mkWpFun (WpCast co1) (WpCast co2) _ _ = WpCast (mkTcFunCo Representational (mkTcSymCo co1) co2)
+mkWpFun WpHole (WpCast co2) t1 _ = WpCast (mkFunCo Representational (mkRepReflCo t1) co2)
+mkWpFun (WpCast co1) WpHole _ t2 = WpCast (mkFunCo Representational (mkSymCo co1) (mkRepReflCo t2))
+mkWpFun (WpCast co1) (WpCast co2) _ _ = WpCast (mkFunCo Representational (mkSymCo co1) co2)
mkWpFun co1 co2 t1 t2 = WpFun co1 co2 t1 t2
mkWpCastR :: TcCoercionR -> HsWrapper
@@ -621,7 +219,7 @@ mkWpEvApps :: [EvTerm] -> HsWrapper
mkWpEvApps args = mk_co_app_fn WpEvApp args
mkWpEvVarApps :: [EvVar] -> HsWrapper
-mkWpEvVarApps vs = mkWpEvApps (map EvId vs)
+mkWpEvVarApps vs = mk_co_app_fn WpEvApp (map EvId vs)
mkWpTyLams :: [TyVar] -> HsWrapper
mkWpTyLams ids = mk_co_lam_fn WpTyLam ids
@@ -668,7 +266,7 @@ data TcEvBinds
deriving( Data.Typeable )
data EvBindsVar = EvBindsVar (IORef EvBindMap) Unique
- -- The Unique is only for debug printing
+ -- The Unique is for debug printing only
instance Data.Data TcEvBinds where
-- Placeholder; we can't travers into TcEvBinds
@@ -727,22 +325,26 @@ data EvBind
-- See Note [Tracking redundant constraints] in TcSimplify
}
+evBindVar :: EvBind -> EvVar
+evBindVar = eb_lhs
+
mkWantedEvBind :: EvVar -> EvTerm -> EvBind
mkWantedEvBind ev tm = EvBind { eb_is_given = False, eb_lhs = ev, eb_rhs = tm }
+
mkGivenEvBind :: EvVar -> EvTerm -> EvBind
mkGivenEvBind ev tm = EvBind { eb_is_given = True, eb_lhs = ev, eb_rhs = tm }
data EvTerm
= EvId EvId -- Any sort of evidence Id, including coercions
- | EvCoercion TcCoercion -- (Boxed) coercion bindings
+ | EvCoercion TcCoercion -- coercion bindings
-- See Note [Coercion evidence terms]
- | EvCast EvTerm TcCoercion -- d |> co, the coercion being at role representational
+ | EvCast EvTerm TcCoercionR -- d |> co
| EvDFunApp DFunId -- Dictionary instance application
- [Type] [EvId]
+ [Type] [EvTerm]
| EvDelayedError Type FastString -- Used with Opt_DeferTypeErrors
-- See Note [Deferring coercion errors to runtime]
@@ -765,7 +367,8 @@ data EvTerm
-- | Instructions on how to make a 'Typeable' dictionary.
-- See Note [Typeable evidence terms]
data EvTypeable
- = EvTypeableTyCon -- ^ Dictionary for @Typeable (T k1..kn)@
+ = EvTypeableTyCon [EvTerm] -- ^ Dictionary for @Typeable (T k1..kn)@.
+ -- The EvTerms are for the arguments
| EvTypeableTyApp EvTerm EvTerm
-- ^ Dictionary for @Typeable (s t)@,
@@ -806,7 +409,7 @@ inside can be EvIds. Eg
Here for the (Typeable [a]) dictionary passed to typeRep we make
evidence
dl :: Typeable [a] = EvTypeable [a]
- (EvTypeableTyApp EvTypeableTyCon (EvId d))
+ (EvTypeableTyApp (EvTypeableTyCon []) (EvId d))
where
d :: Typable a
is the lambda-bound dictionary passed into f.
@@ -814,14 +417,14 @@ is the lambda-bound dictionary passed into f.
Note [Coercion evidence terms]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A "coercion evidence term" takes one of these forms
- co_tm ::= EvId v where v :: t1 ~ t2
+ co_tm ::= EvId v where v :: t1 ~# t2
| EvCoercion co
| EvCast co_tm co
We do quite often need to get a TcCoercion from an EvTerm; see
'evTermCoercion'.
-INVARIANT: The evidence for any constraint with type (t1~t2) is
+INVARIANT: The evidence for any constraint with type (t1 ~# t2) is
a coercion evidence term. Consider for example
[G] d :: F Int a
If we have
@@ -1037,17 +640,17 @@ isEmptyTcEvBinds (TcEvBinds {}) = panic "isEmptyTcEvBinds"
evTermCoercion :: EvTerm -> TcCoercion
-- Applied only to EvTerms of type (s~t)
-- See Note [Coercion evidence terms]
-evTermCoercion (EvId v) = mkTcCoVarCo v
+evTermCoercion (EvId v) = mkCoVarCo v
evTermCoercion (EvCoercion co) = co
-evTermCoercion (EvCast tm co) = TcCastCo (evTermCoercion tm) co
+evTermCoercion (EvCast tm co) = mkCoCast (evTermCoercion tm) co
evTermCoercion tm = pprPanic "evTermCoercion" (ppr tm)
evVarsOfTerm :: EvTerm -> VarSet
evVarsOfTerm (EvId v) = unitVarSet v
-evVarsOfTerm (EvCoercion co) = coVarsOfTcCo co
-evVarsOfTerm (EvDFunApp _ _ evs) = mkVarSet evs
+evVarsOfTerm (EvCoercion co) = coVarsOfCo co
+evVarsOfTerm (EvDFunApp _ _ evs) = mapUnionVarSet evVarsOfTerm evs
evVarsOfTerm (EvSuperClass v _) = evVarsOfTerm v
-evVarsOfTerm (EvCast tm co) = evVarsOfTerm tm `unionVarSet` coVarsOfTcCo co
+evVarsOfTerm (EvCast tm co) = evVarsOfTerm tm `unionVarSet` coVarsOfCo co
evVarsOfTerm (EvDelayedError _ _) = emptyVarSet
evVarsOfTerm (EvLit _) = emptyVarSet
evVarsOfTerm (EvCallStack cs) = evVarsOfCallStack cs
@@ -1056,6 +659,18 @@ evVarsOfTerm (EvTypeable _ ev) = evVarsOfTypeable ev
evVarsOfTerms :: [EvTerm] -> VarSet
evVarsOfTerms = mapUnionVarSet evVarsOfTerm
+-- | Do SCC analysis on a bag of 'EvBind's.
+sccEvBinds :: Bag EvBind -> [SCC EvBind]
+sccEvBinds bs = stronglyConnCompFromEdgedVertices edges
+ where
+ edges :: [(EvBind, EvVar, [EvVar])]
+ edges = foldrBag ((:) . mk_node) [] bs
+
+ mk_node :: EvBind -> (EvBind, EvVar, [EvVar])
+ mk_node b@(EvBind { eb_lhs = var, eb_rhs = term })
+ = (b, var, varSetElems (evVarsOfTerm term `unionVarSet`
+ coVarsOfType (varType var)))
+
evVarsOfCallStack :: EvCallStack -> VarSet
evVarsOfCallStack cs = case cs of
EvCsEmpty -> emptyVarSet
@@ -1065,7 +680,7 @@ evVarsOfCallStack cs = case cs of
evVarsOfTypeable :: EvTypeable -> VarSet
evVarsOfTypeable ev =
case ev of
- EvTypeableTyCon -> emptyVarSet
+ EvTypeableTyCon es -> evVarsOfTerms es
EvTypeableTyApp e1 e2 -> evVarsOfTerms [e1,e2]
EvTypeableTyLit e -> evVarsOfTerm e
@@ -1084,7 +699,10 @@ pprHsWrapper :: SDoc -> HsWrapper -> SDoc
-- In debug mode, print the wrapper
-- otherwise just print what's inside
pprHsWrapper doc wrap
- = getPprStyle (\ s -> if debugStyle s then (help (add_parens doc) wrap False) else doc)
+ = sdocWithDynFlags $ \ dflags ->
+ getPprStyle (\ s -> if debugStyle s || gopt Opt_PrintExplicitCoercions dflags
+ then (help (add_parens doc) wrap False)
+ else doc )
where
help :: (Bool -> SDoc) -> HsWrapper -> Bool -> SDoc
-- True <=> appears in function application position
@@ -1094,7 +712,7 @@ pprHsWrapper doc wrap
help it (WpFun f1 f2 t1 _) = add_parens $ ptext (sLit "\\(x") <> dcolon <> ppr t1 <> ptext (sLit ").") <+>
help (\_ -> it True <+> help (\_ -> ptext (sLit "x")) f1 True) f2 False
help it (WpCast co) = add_parens $ sep [it False, nest 2 (ptext (sLit "|>")
- <+> pprParendTcCo co)]
+ <+> pprParendCo co)]
help it (WpEvApp id) = no_parens $ sep [it True, nest 2 (ppr id)]
help it (WpTyApp ty) = no_parens $ sep [it True, ptext (sLit "@") <+> pprParendType ty]
help it (WpEvLam id) = add_parens $ sep [ ptext (sLit "\\") <> pp_bndr id, it False]
@@ -1115,6 +733,9 @@ instance Outputable TcEvBinds where
instance Outputable EvBindsVar where
ppr (EvBindsVar _ u) = ptext (sLit "EvBindsVar") <> angleBrackets (ppr u)
+instance Uniquable EvBindsVar where
+ getUnique (EvBindsVar _ u) = u
+
instance Outputable EvBind where
ppr (EvBind { eb_lhs = v, eb_rhs = e, eb_is_given = is_given })
= sep [ pp_gw <+> ppr v
@@ -1124,14 +745,14 @@ instance Outputable EvBind where
-- We cheat a bit and pretend EqVars are CoVars for the purposes of pretty printing
instance Outputable EvTerm where
- ppr (EvId v) = ppr v
- ppr (EvCast v co) = ppr v <+> (ptext (sLit "`cast`")) <+> pprParendTcCo co
- ppr (EvCoercion co) = ptext (sLit "CO") <+> ppr co
- ppr (EvSuperClass d n) = ptext (sLit "sc") <> parens (ppr (d,n))
- ppr (EvDFunApp df tys ts) = ppr df <+> sep [ char '@' <> ppr tys, ppr ts ]
- ppr (EvLit l) = ppr l
- ppr (EvCallStack cs) = ppr cs
- ppr (EvDelayedError ty msg) = ptext (sLit "error")
+ ppr (EvId v) = ppr v
+ ppr (EvCast v co) = ppr v <+> (ptext (sLit "`cast`")) <+> pprParendCo co
+ ppr (EvCoercion co) = ptext (sLit "CO") <+> ppr co
+ ppr (EvSuperClass d n) = ptext (sLit "sc") <> parens (ppr (d,n))
+ ppr (EvDFunApp df tys ts) = ppr df <+> sep [ char '@' <> ppr tys, ppr ts ]
+ ppr (EvLit l) = ppr l
+ ppr (EvCallStack cs) = ppr cs
+ ppr (EvDelayedError ty msg) = ptext (sLit "error")
<+> sep [ char '@' <> ppr ty, ppr msg ]
ppr (EvTypeable ty ev) = ppr ev <+> dcolon <+> ptext (sLit "Typeable") <+> ppr ty
@@ -1148,7 +769,7 @@ instance Outputable EvCallStack where
= angleBrackets (ppr (name,loc)) <+> ptext (sLit ":") <+> ppr tm
instance Outputable EvTypeable where
- ppr EvTypeableTyCon = ptext (sLit "TC")
+ ppr (EvTypeableTyCon ts) = ptext (sLit "TC") <+> ppr ts
ppr (EvTypeableTyApp t1 t2) = parens (ppr t1 <+> ppr t2)
ppr (EvTypeableTyLit t1) = ptext (sLit "TyLit") <> ppr t1
@@ -1166,7 +787,7 @@ instance Outputable EvTypeable where
unwrapIP :: Type -> CoercionR
unwrapIP ty =
case unwrapNewTyCon_maybe tc of
- Just (_,_,ax) -> mkUnbranchedAxInstCo Representational ax tys
+ Just (_,_,ax) -> mkUnbranchedAxInstCo Representational ax tys []
Nothing -> pprPanic "unwrapIP" $
text "The dictionary for" <+> quotes (ppr tc)
<+> text "is not a newtype!"