diff options
author | Kavon Farvardin <kavon@farvard.in> | 2018-09-23 15:29:37 -0500 |
---|---|---|
committer | Kavon Farvardin <kavon@farvard.in> | 2018-09-23 15:29:37 -0500 |
commit | 84c2ad99582391005b5e873198b15e9e9eb4f78d (patch) | |
tree | caa8c2f2ec7e97fbb4977263c6817c9af5025cf4 /compiler/types | |
parent | 8ddb47cfcf5776e9a3c55fd37947c8a95e00fa12 (diff) | |
parent | e68b439fe5de61b9a2ca51af472185c62ccb8b46 (diff) | |
download | haskell-wip/T13904.tar.gz |
update to current master againwip/T13904
Diffstat (limited to 'compiler/types')
-rw-r--r-- | compiler/types/Class.hs | 73 | ||||
-rw-r--r-- | compiler/types/CoAxiom.hs | 6 | ||||
-rw-r--r-- | compiler/types/Coercion.hs | 1626 | ||||
-rw-r--r-- | compiler/types/Coercion.hs-boot | 17 | ||||
-rw-r--r-- | compiler/types/FamInstEnv.hs | 325 | ||||
-rw-r--r-- | compiler/types/InstEnv.hs | 81 | ||||
-rw-r--r-- | compiler/types/Kind.hs | 67 | ||||
-rw-r--r-- | compiler/types/OptCoercion.hs | 520 | ||||
-rw-r--r-- | compiler/types/TyCoRep.hs | 1295 | ||||
-rw-r--r-- | compiler/types/TyCoRep.hs-boot | 10 | ||||
-rw-r--r-- | compiler/types/TyCon.hs | 479 | ||||
-rw-r--r-- | compiler/types/TyCon.hs-boot | 2 | ||||
-rw-r--r-- | compiler/types/Type.hs | 1124 | ||||
-rw-r--r-- | compiler/types/Type.hs-boot | 16 | ||||
-rw-r--r-- | compiler/types/Unify.hs | 499 |
15 files changed, 4002 insertions, 2138 deletions
diff --git a/compiler/types/Class.hs b/compiler/types/Class.hs index ae1047ebde..a50135bd7b 100644 --- a/compiler/types/Class.hs +++ b/compiler/types/Class.hs @@ -17,13 +17,14 @@ module Class ( mkClass, mkAbstractClass, classTyVars, classArity, classKey, className, classATs, classATItems, classTyCon, classMethods, classOpItems, classBigSig, classExtraBigSig, classTvsFds, classSCTheta, - classAllSelIds, classSCSelId, classMinimalDef, classHasFds, + classAllSelIds, classSCSelId, classSCSelIds, classMinimalDef, classHasFds, isAbstractClass, - naturallyCoherentClass ) where #include "HsVersions.h" +import GhcPrelude + import {-# SOURCE #-} TyCon ( TyCon ) import {-# SOURCE #-} TyCoRep ( Type, PredType, pprType ) import Var @@ -32,8 +33,6 @@ import BasicTypes import Unique import Util import SrcLoc -import PrelNames ( eqTyConKey, coercibleTyConKey, typeableClassKey, - heqTyConKey ) import Outputable import BooleanFormula (BooleanFormula, mkTrue) @@ -60,6 +59,10 @@ data Class classTyVars :: [TyVar], -- The class kind and type variables; -- identical to those of the TyCon + -- If you want visibility info, look at the classTyCon + -- This field is redundant because it's duplicated in the + -- classTyCon, but classTyVars is used quite often, so maybe + -- it's a bit faster to cache it here classFunDeps :: [FunDep TyVar], -- The functional dependencies @@ -104,23 +107,23 @@ data ClassBody -- Superclasses: eg: (F a ~ b, F b ~ G a, Eq a, Show b) -- We need value-level selectors for both the dictionary -- superclasses and the equality superclasses - classSCThetaStuff :: [PredType], -- Immediate superclasses, - classSCSels :: [Id], -- Selector functions to extract the + cls_sc_theta :: [PredType], -- Immediate superclasses, + cls_sc_sel_ids :: [Id], -- Selector functions to extract the -- superclasses from a -- dictionary of this class -- Associated types - classATStuff :: [ClassATItem], -- Associated type families + cls_ats :: [ClassATItem], -- Associated type families -- Class operations (methods, not superclasses) - classOpStuff :: [ClassOpItem], -- Ordered by tag + cls_ops :: [ClassOpItem], -- Ordered by tag -- Minimal complete definition - classMinimalDefStuff :: ClassMinimalDef + cls_min_def :: ClassMinimalDef } -- TODO: maybe super classes should be allowed in abstract class definitions classMinimalDef :: Class -> ClassMinimalDef -classMinimalDef Class{ classBody = ConcreteClass{ classMinimalDefStuff = d } } = d +classMinimalDef Class{ classBody = ConcreteClass{ cls_min_def = d } } = d classMinimalDef _ = mkTrue -- TODO: make sure this is the right direction {- @@ -178,11 +181,11 @@ mkClass cls_name tyvars fds super_classes superdict_sels at_stuff classTyVars = tyvars, classFunDeps = fds, classBody = ConcreteClass { - classSCThetaStuff = super_classes, - classSCSels = superdict_sels, - classATStuff = at_stuff, - classOpStuff = op_stuff, - classMinimalDefStuff = mindef + cls_sc_theta = super_classes, + cls_sc_sel_ids = superdict_sels, + cls_ats = at_stuff, + cls_ops = op_stuff, + cls_min_def = mindef }, classTyCon = tycon } @@ -236,41 +239,47 @@ classArity clas = length (classTyVars clas) classAllSelIds :: Class -> [Id] -- Both superclass-dictionary and method selectors -classAllSelIds c@(Class { classBody = ConcreteClass { classSCSels = sc_sels }}) +classAllSelIds c@(Class { classBody = ConcreteClass { cls_sc_sel_ids = sc_sels }}) = sc_sels ++ classMethods c classAllSelIds c = ASSERT( null (classMethods c) ) [] +classSCSelIds :: Class -> [Id] +-- Both superclass-dictionary and method selectors +classSCSelIds (Class { classBody = ConcreteClass { cls_sc_sel_ids = sc_sels }}) + = sc_sels +classSCSelIds c = ASSERT( null (classMethods c) ) [] + classSCSelId :: Class -> Int -> Id -- Get the n'th superclass selector Id -- where n is 0-indexed, and counts -- *all* superclasses including equalities -classSCSelId (Class { classBody = ConcreteClass { classSCSels = sc_sels } }) n +classSCSelId (Class { classBody = ConcreteClass { cls_sc_sel_ids = sc_sels } }) n = ASSERT( n >= 0 && lengthExceeds sc_sels n ) sc_sels !! n classSCSelId c n = pprPanic "classSCSelId" (ppr c <+> ppr n) classMethods :: Class -> [Id] -classMethods (Class { classBody = ConcreteClass { classOpStuff = op_stuff } }) +classMethods (Class { classBody = ConcreteClass { cls_ops = op_stuff } }) = [op_sel | (op_sel, _) <- op_stuff] classMethods _ = [] classOpItems :: Class -> [ClassOpItem] -classOpItems (Class { classBody = ConcreteClass { classOpStuff = op_stuff }}) +classOpItems (Class { classBody = ConcreteClass { cls_ops = op_stuff }}) = op_stuff classOpItems _ = [] classATs :: Class -> [TyCon] -classATs (Class { classBody = ConcreteClass { classATStuff = at_stuff } }) +classATs (Class { classBody = ConcreteClass { cls_ats = at_stuff } }) = [tc | ATI tc _ <- at_stuff] classATs _ = [] classATItems :: Class -> [ClassATItem] -classATItems (Class { classBody = ConcreteClass { classATStuff = at_stuff }}) +classATItems (Class { classBody = ConcreteClass { cls_ats = at_stuff }}) = at_stuff classATItems _ = [] classSCTheta :: Class -> [PredType] -classSCTheta (Class { classBody = ConcreteClass { classSCThetaStuff = theta_stuff }}) +classSCTheta (Class { classBody = ConcreteClass { cls_sc_theta = theta_stuff }}) = theta_stuff classSCTheta _ = [] @@ -286,9 +295,9 @@ classBigSig (Class {classTyVars = tyvars, = (tyvars, [], [], []) classBigSig (Class {classTyVars = tyvars, classBody = ConcreteClass { - classSCThetaStuff = sc_theta, - classSCSels = sc_sels, - classOpStuff = op_stuff + cls_sc_theta = sc_theta, + cls_sc_sel_ids = sc_sels, + cls_ops = op_stuff }}) = (tyvars, sc_theta, sc_sels, op_stuff) @@ -298,8 +307,8 @@ classExtraBigSig (Class {classTyVars = tyvars, classFunDeps = fundeps, = (tyvars, fundeps, [], [], [], []) classExtraBigSig (Class {classTyVars = tyvars, classFunDeps = fundeps, classBody = ConcreteClass { - classSCThetaStuff = sc_theta, classSCSels = sc_sels, - classATStuff = ats, classOpStuff = op_stuff + cls_sc_theta = sc_theta, cls_sc_sel_ids = sc_sels, + cls_ats = ats, cls_ops = op_stuff }}) = (tyvars, fundeps, sc_theta, sc_sels, ats, op_stuff) @@ -307,16 +316,6 @@ isAbstractClass :: Class -> Bool isAbstractClass Class{ classBody = AbstractClass } = True isAbstractClass _ = False --- | If a class is "naturally coherent", then we needn't worry at all, in any --- way, about overlapping/incoherent instances. Just solve the thing! -naturallyCoherentClass :: Class -> Bool --- See also Note [The equality class story] in TysPrim. -naturallyCoherentClass cls - = cls `hasKey` heqTyConKey || - cls `hasKey` eqTyConKey || - cls `hasKey` coercibleTyConKey || - cls `hasKey` typeableClassKey - {- ************************************************************************ * * diff --git a/compiler/types/CoAxiom.hs b/compiler/types/CoAxiom.hs index 6d66fb80b1..7f578ec696 100644 --- a/compiler/types/CoAxiom.hs +++ b/compiler/types/CoAxiom.hs @@ -7,7 +7,7 @@ -- and newtypes module CoAxiom ( - BranchFlag, Branched, Unbranched, BranchIndex, Branches, + BranchFlag, Branched, Unbranched, BranchIndex, Branches(..), manyBranches, unbranched, fromBranches, numBranches, mapAccumBranches, @@ -29,6 +29,8 @@ module CoAxiom ( BuiltInSynFamily(..), trivialBuiltInFamily ) where +import GhcPrelude + import {-# SOURCE #-} TyCoRep ( Type, pprType ) import {-# SOURCE #-} TyCon ( TyCon ) import Outputable @@ -220,6 +222,8 @@ data CoAxBranch -- See Note [CoAxiom locations] , cab_tvs :: [TyVar] -- Bound type variables; not necessarily fresh -- See Note [CoAxBranch type variables] + -- May be eta-reduded; see FamInstEnv + -- Note [Eta reduction for data families] , cab_cvs :: [CoVar] -- Bound coercion variables -- Always empty, for now. -- See Note [Constraints in patterns] diff --git a/compiler/types/Coercion.hs b/compiler/types/Coercion.hs index 3f5036c4dd..c766046ea8 100644 --- a/compiler/types/Coercion.hs +++ b/compiler/types/Coercion.hs @@ -10,8 +10,9 @@ -- module Coercion ( -- * Main data type - Coercion, CoercionN, CoercionR, CoercionP, - UnivCoProvenance, CoercionHole, LeftOrRight(..), + Coercion, CoercionN, CoercionR, CoercionP, MCoercion(..), MCoercionR, + UnivCoProvenance, CoercionHole(..), coHoleCoVar, setCoHoleCoVar, + LeftOrRight(..), Var, CoVar, TyCoVar, Role(..), ltRole, @@ -22,22 +23,22 @@ module Coercion ( coercionRole, coercionKindRole, -- ** Constructing coercions - mkReflCo, mkRepReflCo, mkNomReflCo, + mkGReflCo, mkReflCo, mkRepReflCo, mkNomReflCo, mkCoVarCo, mkCoVarCos, mkAxInstCo, mkUnbranchedAxInstCo, mkAxInstRHS, mkUnbranchedAxInstRHS, mkAxInstLHS, mkUnbranchedAxInstLHS, mkPiCo, mkPiCos, mkCoCast, - mkSymCo, mkTransCo, mkTransAppCo, - mkNthCo, mkNthCoRole, mkLRCo, - mkInstCo, mkAppCo, mkAppCos, mkTyConAppCo, mkFunCo, mkFunCos, - mkForAllCo, mkForAllCos, mkHomoForAllCos, mkHomoForAllCos_NoRefl, - mkPhantomCo, mkHomoPhantomCo, toPhantomCo, + mkSymCo, mkTransCo, + mkNthCo, nthCoRole, mkLRCo, + mkInstCo, mkAppCo, mkAppCos, mkTyConAppCo, mkFunCo, + mkForAllCo, mkForAllCos, mkHomoForAllCos, + mkPhantomCo, mkUnsafeCo, mkHoleCo, mkUnivCo, mkSubCo, mkAxiomInstCo, mkProofIrrelCo, downgradeRole, maybeSubCo, mkAxiomRuleCo, - mkCoherenceCo, mkCoherenceRightCo, mkCoherenceLeftCo, - mkKindCo, castCoercionKind, + mkGReflRightCo, mkGReflLeftCo, mkCoherenceLeftCo, mkCoherenceRightCo, + mkKindCo, castCoercionKind, castCoercionKindI, mkHeteroCoercionType, @@ -48,17 +49,18 @@ module Coercion ( mapStepResult, unwrapNewTypeStepper, topNormaliseNewType_maybe, topNormaliseTypeX, - decomposeCo, decomposeFunCo, getCoVar_maybe, + decomposeCo, decomposeFunCo, decomposePiCos, getCoVar_maybe, splitTyConAppCo_maybe, splitAppCo_maybe, splitFunCo_maybe, splitForAllCo_maybe, + splitForAllCo_ty_maybe, splitForAllCo_co_maybe, nthRole, tyConRolesX, tyConRolesRepresentational, setNominalRole_maybe, pickLR, - isReflCo, isReflCo_maybe, isReflexiveCo, isReflexiveCo_maybe, + isGReflCo, isReflCo, isReflCo_maybe, isGReflCo_maybe, isReflexiveCo, isReflexiveCo_maybe, isReflCoVar_maybe, -- ** Coercion variables @@ -79,11 +81,11 @@ module Coercion ( -- ** Lifting liftCoSubst, liftCoSubstTyVar, liftCoSubstWith, liftCoSubstWithEx, - emptyLiftingContext, extendLiftingContext, - liftCoSubstVarBndrCallback, isMappedByLC, + emptyLiftingContext, extendLiftingContext, extendLiftingContextAndInScope, + liftCoSubstVarBndrUsing, isMappedByLC, mkSubstLiftingContext, zapLiftingContext, - substForAllCoBndrCallbackLC, lcTCvSubst, lcInScopeSet, + substForAllCoBndrUsingLC, lcTCvSubst, lcInScopeSet, LiftCoEnv, LiftingContext(..), liftEnvSubstLeft, liftEnvSubstRight, substRightCo, substLeftCo, swapLiftCoEnv, lcSubstLeft, lcSubstRight, @@ -95,24 +97,27 @@ module Coercion ( seqCo, -- * Pretty-printing - pprCo, pprParendCo, pprCoBndr, + pprCo, pprParendCo, pprCoAxiom, pprCoAxBranch, pprCoAxBranchHdr, -- * Tidying tidyCo, tidyCos, -- * Other - promoteCoercion + promoteCoercion, buildCoercion ) where #include "HsVersions.h" +import GhcPrelude + import TyCoRep import Type import TyCon import CoAxiom import Var import VarEnv +import VarSet import Name hiding ( varName ) import Util import BasicTypes @@ -126,8 +131,7 @@ import ListSetOps import Maybes import UniqFM -import Control.Monad (foldM) -import Control.Arrow ( first ) +import Control.Monad (foldM, zipWithM) import Data.Function ( on ) {- @@ -152,117 +156,36 @@ setCoVarUnique = setVarUnique setCoVarName :: CoVar -> Name -> CoVar setCoVarName = setVarName - {- %************************************************************************ %* * - Pretty-printing coercions + Pretty-printing CoAxioms %* * %************************************************************************ -@pprCo@ is the standard @Coercion@ printer; the overloaded @ppr@ -function is defined to use this. @pprParendCo@ is the same, except it -puts parens around the type, except for the atomic cases. -@pprParendCo@ works just by setting the initial context precedence -very high. --} - --- Outputable instances are in TyCoRep, to avoid orphans - -pprCo, pprParendCo :: Coercion -> SDoc -pprCo co = ppr_co TopPrec co -pprParendCo co = ppr_co TyConPrec co - -ppr_co :: TyPrec -> Coercion -> SDoc -ppr_co _ (Refl r ty) = angleBrackets (ppr ty) <> ppr_role r - -ppr_co _ (TyConAppCo r tc cos) = pprTcAppCo TyConPrec ppr_co tc cos <> ppr_role r -ppr_co p (AppCo co arg) = maybeParen p TyConPrec $ - pprCo co <+> ppr_co TyConPrec arg -ppr_co p co@(ForAllCo {}) = ppr_forall_co p co -ppr_co p co@(FunCo {}) = ppr_fun_co p co -ppr_co _ (CoVarCo cv) = parenSymOcc (getOccName cv) (ppr cv) -ppr_co p (AxiomInstCo con index args) - = pprPrefixApp p (ppr (getName con) <> brackets (ppr index)) - (map (ppr_co TyConPrec) args) - -ppr_co p co@(TransCo {}) = maybeParen p FunPrec $ - case trans_co_list co [] of - [] -> panic "ppr_co" - (co:cos) -> sep ( ppr_co FunPrec co - : [ char ';' <+> ppr_co FunPrec co | co <- cos]) -ppr_co p (InstCo co arg) = maybeParen p TyConPrec $ - pprParendCo co <> text "@" <> ppr_co TopPrec arg - -ppr_co p (UnivCo UnsafeCoerceProv r ty1 ty2) - = pprPrefixApp p (text "UnsafeCo" <+> ppr r) - [pprParendType ty1, pprParendType ty2] -ppr_co _ (UnivCo p r t1 t2) - = char 'U' - <> parens (ppr_prov <> comma <+> ppr t1 <> comma <+> ppr t2) - <> ppr_role r - where - ppr_prov = case p of - HoleProv h -> text "hole:" <> ppr h - PhantomProv kind_co -> text "phant:" <> ppr kind_co - ProofIrrelProv co -> text "irrel:" <> ppr co - PluginProv s -> text "plugin:" <> text s - UnsafeCoerceProv -> text "unsafe" - -ppr_co p (SymCo co) = pprPrefixApp p (text "Sym") [pprParendCo co] -ppr_co p (NthCo n co) = pprPrefixApp p (text "Nth:" <> int n) [pprParendCo co] -ppr_co p (LRCo sel co) = pprPrefixApp p (ppr sel) [pprParendCo co] -ppr_co p (CoherenceCo c1 c2) = maybeParen p TyConPrec $ - (ppr_co FunPrec c1) <+> (text "|>") <+> - (ppr_co FunPrec c2) -ppr_co p (KindCo co) = pprPrefixApp p (text "kind") [pprParendCo co] -ppr_co p (SubCo co) = pprPrefixApp p (text "Sub") [pprParendCo co] -ppr_co p (AxiomRuleCo co cs) = maybeParen p TopPrec $ ppr_axiom_rule_co co cs - -ppr_axiom_rule_co :: CoAxiomRule -> [Coercion] -> SDoc -ppr_axiom_rule_co co ps = ppr (coaxrName co) <+> parens (interpp'SP ps) - -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' - -trans_co_list :: Coercion -> [Coercion] -> [Coercion] -trans_co_list (TransCo co1 co2) cos = trans_co_list co1 (trans_co_list co2 cos) -trans_co_list co cos = co : cos - -ppr_fun_co :: TyPrec -> Coercion -> SDoc -ppr_fun_co p co = pprArrowChain p (split co) - where - split :: Coercion -> [SDoc] - split (FunCo _ arg res) - = ppr_co FunPrec arg : split res - split co = [ppr_co TopPrec co] - -ppr_forall_co :: TyPrec -> Coercion -> SDoc -ppr_forall_co p (ForAllCo tv h co) - = maybeParen p FunPrec $ - sep [pprCoBndr (tyVarName tv) h, ppr_co TopPrec co] -ppr_forall_co _ _ = panic "ppr_forall_co" +Defined here to avoid module loops. CoAxiom is loaded very early on. -pprCoBndr :: Name -> Coercion -> SDoc -pprCoBndr name eta = - forAllLit <+> parens (ppr name <+> dcolon <+> ppr eta) <> dot +-} pprCoAxiom :: CoAxiom br -> SDoc pprCoAxiom ax@(CoAxiom { co_ax_branches = branches }) = hang (text "axiom" <+> ppr ax <+> dcolon) - 2 (vcat (map (ppr_co_ax_branch (const ppr) ax) $ fromBranches branches)) + 2 (vcat (map (ppr_co_ax_branch (\_ ty -> equals <+> pprType ty) ax) $ + fromBranches branches)) pprCoAxBranch :: CoAxiom br -> CoAxBranch -> SDoc pprCoAxBranch = ppr_co_ax_branch pprRhs where - pprRhs fam_tc (TyConApp tycon _) + pprRhs fam_tc rhs | isDataFamilyTyCon fam_tc - = pprDataCons tycon - pprRhs _ rhs = ppr rhs + = empty -- Don't bother printing anything for the RHS of a data family + -- instance... + + | otherwise + = equals <+> ppr rhs + -- ...but for a type family instance, do print out the RHS, since + -- it might be needed to disambiguate between duplicate instances + -- (#14179) pprCoAxBranchHdr :: CoAxiom br -> BranchIndex -> SDoc pprCoAxBranchHdr ax index = pprCoAxBranch ax (coAxiomNthBranch ax index) @@ -276,8 +199,8 @@ ppr_co_ax_branch ppr_rhs , cab_rhs = rhs , cab_loc = loc }) = foldr1 (flip hangNotEmpty 2) - [ pprUserForAll (mkTyVarBinders Inferred (tvs ++ cvs)) - , pprTypeApp fam_tc lhs <+> equals <+> ppr_rhs fam_tc rhs + [ pprUserForAll (mkTyCoVarBinders Inferred (ee_tvs ++ cvs)) + , pprTypeApp fam_tc ee_lhs <+> ppr_rhs fam_tc rhs , text "-- Defined" <+> pprLoc loc ] where pprLoc loc @@ -288,6 +211,21 @@ ppr_co_ax_branch ppr_rhs = text "in" <+> quotes (ppr (nameModule name)) + (ee_tvs, ee_lhs) + | Just (tycon, tc_args) <- splitTyConApp_maybe rhs + , isDataFamilyTyCon fam_tc + = -- Eta-expand LHS types, because sometimes data family instances + -- are eta-reduced. + -- See Note [Eta reduction for data family axioms] in TcInstDecls. + let tc_tvs = tyConTyVars tycon + etad_tvs = dropList tc_args tc_tvs + etad_tys = mkTyVarTys etad_tvs + eta_expanded_tvs = tvs `chkAppend` etad_tvs + eta_expanded_lhs = lhs `chkAppend` etad_tys + in (eta_expanded_tvs, eta_expanded_lhs) + | otherwise + = (tvs, lhs) + {- %************************************************************************ %* * @@ -311,22 +249,114 @@ where co_rep1, co_rep2 are the coercions on the representations. -- | This breaks a 'Coercion' with type @T A B C ~ T D E F@ into -- a list of 'Coercion's of kinds @A ~ D@, @B ~ E@ and @E ~ F@. Hence: -- --- > decomposeCo 3 c = [nth 0 c, nth 1 c, nth 2 c] -decomposeCo :: Arity -> Coercion -> [Coercion] -decomposeCo arity co - = [mkNthCo n co | n <- [0..(arity-1)] ] +-- > decomposeCo 3 c [r1, r2, r3] = [nth r1 0 c, nth r2 1 c, nth r3 2 c] +decomposeCo :: Arity -> Coercion + -> [Role] -- the roles of the output coercions + -- this must have at least as many + -- entries as the Arity provided + -> [Coercion] +decomposeCo arity co rs + = [mkNthCo r n co | (n,r) <- [0..(arity-1)] `zip` rs ] -- Remember, Nth is zero-indexed -decomposeFunCo :: Coercion -> (Coercion, Coercion) +decomposeFunCo :: HasDebugCallStack + => Role -- Role of the input coercion + -> Coercion -- Input coercion + -> (Coercion, Coercion) -- Expects co :: (s1 -> t1) ~ (s2 -> t2) -- Returns (co1 :: s1~s2, co2 :: t1~t2) -- See Note [Function coercions] for the "2" and "3" -decomposeFunCo co = ASSERT2( all_ok, ppr co ) - (mkNthCo 2 co, mkNthCo 3 co) +decomposeFunCo r co = ASSERT2( all_ok, ppr co ) + (mkNthCo r 2 co, mkNthCo r 3 co) where Pair s1t1 s2t2 = coercionKind co all_ok = isFunTy s1t1 && isFunTy s2t2 +{- Note [Pushing a coercion into a pi-type] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Suppose we have this: + (f |> co) t1 .. tn +Then we want to push the coercion into the arguments, so as to make +progress. For example of why you might want to do so, see Note +[Respecting definitional equality] in TyCoRep. + +This is done by decomposePiCos. Specifically, if + decomposePiCos co [t1,..,tn] = ([co1,...,cok], cor) +then + (f |> co) t1 .. tn = (f (t1 |> co1) ... (tk |> cok)) |> cor) t(k+1) ... tn + +Notes: + +* k can be smaller than n! That is decomposePiCos can return *fewer* + coercions than there are arguments (ie k < n), if the kind provided + doesn't have enough binders. + +* If there is a type error, we might see + (f |> co) t1 + where co :: (forall a. ty) ~ (ty1 -> ty2) + Here 'co' is insoluble, but we don't want to crash in decoposePiCos. + So decomposePiCos carefully tests both sides of the coercion to check + they are both foralls or both arrows. Not doing this caused Trac #15343. +-} + +decomposePiCos :: HasDebugCallStack + => CoercionN -> Pair Type -- Coercion and its kind + -> [Type] + -> ([CoercionN], CoercionN) +-- See Note [Pushing a coercion into a pi-type] +decomposePiCos orig_co (Pair orig_k1 orig_k2) orig_args + = go [] (orig_subst,orig_k1) orig_co (orig_subst,orig_k2) orig_args + where + orig_subst = mkEmptyTCvSubst $ mkInScopeSet $ + tyCoVarsOfTypes orig_args `unionVarSet` tyCoVarsOfCo orig_co + + go :: [CoercionN] -- accumulator for argument coercions, reversed + -> (TCvSubst,Kind) -- Lhs kind of coercion + -> CoercionN -- coercion originally applied to the function + -> (TCvSubst,Kind) -- Rhs kind of coercion + -> [Type] -- Arguments to that function + -> ([CoercionN], Coercion) + -- Invariant: co :: subst1(k2) ~ subst2(k2) + + go acc_arg_cos (subst1,k1) co (subst2,k2) (ty:tys) + | Just (a, t1) <- splitForAllTy_maybe k1 + , Just (b, t2) <- splitForAllTy_maybe k2 + -- know co :: (forall a:s1.t1) ~ (forall b:s2.t2) + -- function :: forall a:s1.t1 (the function is not passed to decomposePiCos) + -- a :: s1 + -- b :: s2 + -- ty :: s2 + -- need arg_co :: s2 ~ s1 + -- res_co :: t1[ty |> arg_co / a] ~ t2[ty / b] + = let arg_co = mkNthCo Nominal 0 (mkSymCo co) + res_co = mkInstCo co (mkGReflLeftCo Nominal ty arg_co) + subst1' = extendTCvSubst subst1 a (ty `CastTy` arg_co) + subst2' = extendTCvSubst subst2 b ty + in + go (arg_co : acc_arg_cos) (subst1', t1) res_co (subst2', t2) tys + + | Just (_s1, t1) <- splitFunTy_maybe k1 + , Just (_s2, t2) <- splitFunTy_maybe k2 + -- know co :: (s1 -> t1) ~ (s2 -> t2) + -- function :: s1 -> t1 + -- ty :: s2 + -- need arg_co :: s2 ~ s1 + -- res_co :: t1 ~ t2 + = let (sym_arg_co, res_co) = decomposeFunCo Nominal co + arg_co = mkSymCo sym_arg_co + in + go (arg_co : acc_arg_cos) (subst1,t1) res_co (subst2,t2) tys + + | not (isEmptyTCvSubst subst1) || not (isEmptyTCvSubst subst2) + = go acc_arg_cos (zapTCvSubst subst1, substTy subst1 k1) + co + (zapTCvSubst subst2, substTy subst1 k2) + (ty:tys) + + -- tys might not be empty, if the left-hand type of the original coercion + -- didn't have enough binders + go acc_arg_cos _ki1 co _ki2 _tys = (reverse acc_arg_cos, co) + -- | Attempts to obtain the type variable underlying a 'Coercion' getCoVar_maybe :: Coercion -> Maybe CoVar getCoVar_maybe (CoVarCo cv) = Just cv @@ -335,7 +365,8 @@ getCoVar_maybe _ = Nothing -- | Attempts to tease a coercion apart into a type constructor and the application -- of a number of coercion arguments to that constructor splitTyConAppCo_maybe :: Coercion -> Maybe (TyCon, [Coercion]) -splitTyConAppCo_maybe (Refl r ty) +splitTyConAppCo_maybe co + | Just (ty, r) <- isReflCo_maybe co = do { (tc, tys) <- splitTyConApp_maybe ty ; let args = zipWith mkReflCo (tyConRolesX r tc) tys ; return (tc, args) } @@ -349,16 +380,21 @@ splitAppCo_maybe :: Coercion -> Maybe (Coercion, Coercion) -- ^ Attempt to take a coercion application apart. splitAppCo_maybe (AppCo co arg) = Just (co, arg) splitAppCo_maybe (TyConAppCo r tc args) - | mightBeUnsaturatedTyCon tc || args `lengthExceeds` tyConArity tc + | args `lengthExceeds` tyConArity tc + , Just (args', arg') <- snocView args + = Just ( mkTyConAppCo r tc args', arg' ) + + | mightBeUnsaturatedTyCon tc -- Never create unsaturated type family apps! , Just (args', arg') <- snocView args - , Just arg'' <- setNominalRole_maybe arg' + , Just arg'' <- setNominalRole_maybe (nthRole r tc (length args')) arg' = Just ( mkTyConAppCo r tc args', arg'' ) -- Use mkTyConAppCo to preserve the invariant -- that identity coercions are always represented by Refl -splitAppCo_maybe (Refl r ty) - | Just (ty1, ty2) <- splitAppTy_maybe ty +splitAppCo_maybe co + | Just (ty, r) <- isReflCo_maybe co + , Just (ty1, ty2) <- splitAppTy_maybe ty = Just (mkReflCo r ty1, mkNomReflCo ty2) splitAppCo_maybe _ = Nothing @@ -366,19 +402,31 @@ splitFunCo_maybe :: Coercion -> Maybe (Coercion, Coercion) splitFunCo_maybe (FunCo _ arg res) = Just (arg, res) splitFunCo_maybe _ = Nothing -splitForAllCo_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion) +splitForAllCo_maybe :: Coercion -> Maybe (TyCoVar, Coercion, Coercion) splitForAllCo_maybe (ForAllCo tv k_co co) = Just (tv, k_co, co) splitForAllCo_maybe _ = Nothing +-- | Like 'splitForAllCo_maybe', but only returns Just for tyvar binder +splitForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion) +splitForAllCo_ty_maybe (ForAllCo tv k_co co) + | isTyVar tv = Just (tv, k_co, co) +splitForAllCo_ty_maybe _ = Nothing + +-- | Like 'splitForAllCo_maybe', but only returns Just for covar binder +splitForAllCo_co_maybe :: Coercion -> Maybe (CoVar, Coercion, Coercion) +splitForAllCo_co_maybe (ForAllCo cv k_co co) + | isCoVar cv = Just (cv, k_co, co) +splitForAllCo_co_maybe _ = Nothing + ------------------------------------------------------- -- and some coercion kind stuff -coVarTypes :: CoVar -> Pair Type +coVarTypes :: HasDebugCallStack => CoVar -> Pair Type coVarTypes cv | (_, _, ty1, ty2, _) <- coVarKindsTypesRole cv = Pair ty1 ty2 -coVarKindsTypesRole :: CoVar -> (Kind,Kind,Type,Type,Role) +coVarKindsTypesRole :: HasDebugCallStack => CoVar -> (Kind,Kind,Type,Type,Role) coVarKindsTypesRole cv | Just (tc, [k1,k2,ty1,ty2]) <- splitTyConApp_maybe (varType cv) = let role @@ -428,33 +476,58 @@ mkHeteroCoercionType Phantom = panic "mkHeteroCoercionType" -- produce a coercion @rep_co :: r1 ~ r2@. mkRuntimeRepCo :: HasDebugCallStack => Coercion -> Coercion mkRuntimeRepCo co - = mkNthCo 0 kind_co + = mkNthCo Nominal 0 kind_co where kind_co = mkKindCo co -- kind_co :: TYPE r1 ~ TYPE r2 -- (up to silliness with Constraint) -isReflCoVar_maybe :: CoVar -> Maybe Coercion +isReflCoVar_maybe :: Var -> Maybe Coercion -- If cv :: t~t then isReflCoVar_maybe cv = Just (Refl t) +-- Works on all kinds of Vars, not just CoVars isReflCoVar_maybe cv - | Pair ty1 ty2 <- coVarTypes cv + | isCoVar cv + , Pair ty1 ty2 <- coVarTypes cv , ty1 `eqType` ty2 - = Just (Refl (coVarRole cv) ty1) + = Just (mkReflCo (coVarRole cv) ty1) | otherwise = Nothing +-- | Tests if this coercion is obviously a generalized reflexive coercion. +-- Guaranteed to work very quickly. +isGReflCo :: Coercion -> Bool +isGReflCo (GRefl{}) = True +isGReflCo (Refl{}) = True -- Refl ty == GRefl N ty MRefl +isGReflCo _ = False + +-- | Tests if this MCoercion is obviously generalized reflexive +-- Guaranteed to work very quickly. +isGReflMCo :: MCoercion -> Bool +isGReflMCo MRefl = True +isGReflMCo (MCo co) | isGReflCo co = True +isGReflMCo _ = False + -- | Tests if this coercion is obviously reflexive. Guaranteed to work -- very quickly. Sometimes a coercion can be reflexive, but not obviously -- so. c.f. 'isReflexiveCo' isReflCo :: Coercion -> Bool -isReflCo (Refl {}) = True -isReflCo _ = False +isReflCo (Refl{}) = True +isReflCo (GRefl _ _ mco) | isGReflMCo mco = True +isReflCo _ = False + +-- | Returns the type coerced if this coercion is a generalized reflexive +-- coercion. Guaranteed to work very quickly. +isGReflCo_maybe :: Coercion -> Maybe (Type, Role) +isGReflCo_maybe (GRefl r ty _) = Just (ty, r) +isGReflCo_maybe (Refl ty) = Just (ty, Nominal) +isGReflCo_maybe _ = Nothing -- | Returns the type coerced if this coercion is reflexive. Guaranteed -- to work very quickly. Sometimes a coercion can be reflexive, but not -- obviously so. c.f. 'isReflexiveCo_maybe' isReflCo_maybe :: Coercion -> Maybe (Type, Role) -isReflCo_maybe (Refl r ty) = Just (ty, r) -isReflCo_maybe _ = Nothing +isReflCo_maybe (Refl ty) = Just (ty, Nominal) +isReflCo_maybe (GRefl r ty mco) | isGReflMCo mco = Just (ty, r) +isReflCo_maybe _ = Nothing -- | Slowly checks if the coercion is reflexive. Don't call this in a loop, -- as it walks over the entire coercion. @@ -464,7 +537,8 @@ isReflexiveCo = isJust . isReflexiveCo_maybe -- | Extracts the coerced type from a reflexive coercion. This potentially -- walks over the entire coercion, so avoid doing this in a loop. isReflexiveCo_maybe :: Coercion -> Maybe (Type, Role) -isReflexiveCo_maybe (Refl r ty) = Just (ty, r) +isReflexiveCo_maybe (Refl ty) = Just (ty, Nominal) +isReflexiveCo_maybe (GRefl r ty mco) | isGReflMCo mco = Just (ty, r) isReflexiveCo_maybe co | ty1 `eqType` ty2 = Just (ty1, r) @@ -532,54 +606,27 @@ One might ask: shouldn't downgradeRole_maybe just use setNominalRole_maybe as appropriate? I (Richard E.) have decided not to do this, because upgrading a role is bizarre and a caller should have to ask for this behavior explicitly. -Note [mkTransAppCo] -~~~~~~~~~~~~~~~~~~~ -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 mkAppCo 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 - - co3' :: Maybe Int ~R a b - -then - - co3' = (Maybe co2') ; (co1' <b>_N) - -This is exactly what `mkTransAppCo` builds for us. Information for all -the arguments tends to be to hand at call sites, so it's quicker than -using, say, coercionKind. - -} +-- | Make a generalized reflexive coercion +mkGReflCo :: Role -> Type -> MCoercionN -> Coercion +mkGReflCo r ty mco + | isGReflMCo mco = if r == Nominal then Refl ty + else GRefl r ty MRefl + | otherwise = GRefl r ty mco + +-- | Make a reflexive coercion mkReflCo :: Role -> Type -> Coercion -mkReflCo r ty - = Refl r ty +mkReflCo Nominal ty = Refl ty +mkReflCo r ty = GRefl r ty MRefl -- | Make a representational reflexive coercion mkRepReflCo :: Type -> Coercion -mkRepReflCo = mkReflCo Representational +mkRepReflCo ty = GRefl Representational ty MRefl -- | Make a nominal reflexive coercion mkNomReflCo :: Type -> Coercion -mkNomReflCo = mkReflCo Nominal +mkNomReflCo = Refl -- | Apply a type constructor to a list of coercions. It is the -- caller's responsibility to get the roles correct on argument coercions. @@ -597,7 +644,8 @@ mkTyConAppCo r tc cos = mkAppCos (liftCoSubst r (mkLiftingContext tv_co_prs) rhs_ty) leftover_cos | Just tys_roles <- traverse isReflCo_maybe cos - = Refl r (mkTyConApp tc (map fst tys_roles)) -- See Note [Refl invariant] + = mkReflCo r (mkTyConApp tc (map fst tys_roles)) + -- See Note [Refl invariant] | otherwise = TyConAppCo r tc cos @@ -608,24 +656,22 @@ mkFunCo r co1 co2 -- See Note [Refl invariant] | Just (ty1, _) <- isReflCo_maybe co1 , Just (ty2, _) <- isReflCo_maybe co2 - = Refl r (mkFunTy ty1 ty2) + = mkReflCo r (mkFunTy ty1 ty2) | otherwise = FunCo r co1 co2 --- | Make nested function 'Coercion's -mkFunCos :: Role -> [Coercion] -> Coercion -> Coercion -mkFunCos r cos res_co = foldr (mkFunCo r) res_co cos - -- | Apply a 'Coercion' to another 'Coercion'. -- The second coercion must be Nominal, unless the first is Phantom. -- If the first is Phantom, then the second can be either Phantom or Nominal. mkAppCo :: Coercion -- ^ :: t1 ~r t2 -> Coercion -- ^ :: s1 ~N s2, where s1 :: k1, s2 :: k2 -> Coercion -- ^ :: t1 s1 ~r t2 s2 -mkAppCo (Refl r ty1) arg - | Just (ty2, _) <- isReflCo_maybe arg - = Refl r (mkAppTy ty1 ty2) +mkAppCo co arg + | Just (ty1, r) <- isReflCo_maybe co + , Just (ty2, _) <- isReflCo_maybe arg + = mkReflCo r (mkAppTy ty1 ty2) - | Just (tc, tys) <- splitTyConApp_maybe ty1 + | Just (ty1, r) <- isReflCo_maybe co + , Just (tc, tys) <- splitTyConApp_maybe ty1 -- Expand type synonyms; a TyConAppCo can't have a type synonym (Trac #9102) = mkTyConAppCo r tc (zip_roles (tyConRolesX r tc) tys) where @@ -650,102 +696,83 @@ mkAppCo co arg = AppCo co arg mkAppCos :: Coercion -> [Coercion] -> Coercion -mkAppCos co1 cos = foldl mkAppCo co1 cos - --- | Like `mkAppCo`, but allows the second coercion to be other than --- nominal. See Note [mkTransAppCo]. Role r3 cannot be more stringent --- than either r1 or r2. -mkTransAppCo :: Role -- ^ r1 - -> Coercion -- ^ co1 :: ty1a ~r1 ty1b - -> Type -- ^ ty1a - -> Type -- ^ ty1b - -> Role -- ^ r2 - -> Coercion -- ^ co2 :: ty2a ~r2 ty2b - -> Type -- ^ ty2a - -> Type -- ^ ty2b - -> Role -- ^ r3 - -> Coercion -- ^ :: ty1a ty2a ~r3 ty1b ty2b -mkTransAppCo r1 co1 ty1a ty1b r2 co2 ty2a ty2b r3 --- How incredibly fiddly! Is there a better way?? - = case (r1, r2, r3) of - (_, _, Phantom) - -> mkPhantomCo kind_co (mkAppTy ty1a ty2a) (mkAppTy ty1b ty2b) - where -- ty1a :: k1a -> k2a - -- ty1b :: k1b -> k2b - -- ty2a :: k1a - -- ty2b :: k1b - -- ty1a ty2a :: k2a - -- ty1b ty2b :: k2b - kind_co1 = mkKindCo co1 -- :: k1a -> k2a ~N k1b -> k2b - kind_co = mkNthCo 1 kind_co1 -- :: k2a ~N k2b - - (_, _, Nominal) - -> ASSERT( r1 == Nominal && r2 == Nominal ) - mkAppCo co1 co2 - (Nominal, Nominal, Representational) - -> mkSubCo (mkAppCo co1 co2) - (_, Nominal, Representational) - -> ASSERT( r1 == Representational ) - mkAppCo co1 co2 - (Nominal, Representational, Representational) - -> go (mkSubCo co1) - (_ , _, Representational) - -> ASSERT( r1 == Representational && r2 == Representational ) - go co1 - where - go co1_repr - | Just (tc1b, tys1b) <- splitTyConApp_maybe ty1b - , nextRole ty1b == r2 - = (mkAppCo co1_repr (mkNomReflCo ty2a)) `mkTransCo` - (mkTyConAppCo Representational tc1b - (zipWith mkReflCo (tyConRolesRepresentational tc1b) tys1b - ++ [co2])) - - | Just (tc1a, tys1a) <- splitTyConApp_maybe ty1a - , nextRole ty1a == r2 - = (mkTyConAppCo Representational tc1a - (zipWith mkReflCo (tyConRolesRepresentational tc1a) tys1a - ++ [co2])) - `mkTransCo` - (mkAppCo co1_repr (mkNomReflCo ty2b)) +mkAppCos co1 cos = foldl' mkAppCo co1 cos - | otherwise - = pprPanic "mkTransAppCo" (vcat [ ppr r1, ppr co1, ppr ty1a, ppr ty1b - , ppr r2, ppr co2, ppr ty2a, ppr ty2b - , ppr r3 ]) +{- Note [Unused coercion variable in ForAllCo] + +See Note [Unused coercion variable in ForAllTy] in TyCoRep for the motivation for +checking coercion variable in types. +To lift the design choice to (ForAllCo cv kind_co body_co), we have two options: + +(1) In mkForAllCo, we check whether cv is a coercion variable + and whether it is not used in body_co. If so we construct a FunCo. +(2) We don't do this check in mkForAllCo. + In coercionKind, we use mkTyCoForAllTy to perform the check and construct + a FunTy when necessary. + +We chose (2) for two reasons: --- | Make a Coercion from a tyvar, a kind coercion, and a body coercion. --- The kind of the tyvar should be the left-hand kind of the kind coercion. -mkForAllCo :: TyVar -> Coercion -> Coercion -> Coercion +* for a coercion, all that matters is its kind, So ForAllCo or FunCo does not + make a difference. +* even if cv occurs in body_co, it is possible that cv does not occur in the kind + of body_co. Therefore the check in coercionKind is inevitable. + +-} + + +-- | Make a Coercion from a tycovar, a kind coercion, and a body coercion. +-- The kind of the tycovar should be the left-hand kind of the kind coercion. +-- See Note [Unused coercion variable in ForAllCo] +mkForAllCo :: TyCoVar -> CoercionN -> Coercion -> Coercion mkForAllCo tv kind_co co - | Refl r ty <- co - , Refl {} <- kind_co - = Refl r (mkInvForAllTy tv ty) + | ASSERT( varType tv `eqType` (pFst $ coercionKind kind_co)) True + , Just (ty, r) <- isReflCo_maybe co + , isGReflCo kind_co + = mkReflCo r (mkTyCoInvForAllTy tv ty) + | otherwise + = ForAllCo tv kind_co co + +-- | Like 'mkForAllCo', but the inner coercion shouldn't be an obvious +-- reflexive coercion. For example, it is guaranteed in 'mkForAllCos'. +-- The kind of the tycovar should be the left-hand kind of the kind coercion. +mkForAllCo_NoRefl :: TyCoVar -> CoercionN -> Coercion -> Coercion +mkForAllCo_NoRefl tv kind_co co + | ASSERT( varType tv `eqType` (pFst $ coercionKind kind_co)) True + , ASSERT( not (isReflCo co)) True + , isCoVar tv + , not (tv `elemVarSet` tyCoVarsOfCo co) + = FunCo (coercionRole co) kind_co co | otherwise = ForAllCo tv kind_co co -- | Make nested ForAllCos -mkForAllCos :: [(TyVar, Coercion)] -> Coercion -> Coercion -mkForAllCos bndrs (Refl r ty) +mkForAllCos :: [(TyCoVar, CoercionN)] -> Coercion -> Coercion +mkForAllCos bndrs co + | Just (ty, r ) <- isReflCo_maybe co = let (refls_rev'd, non_refls_rev'd) = span (isReflCo . snd) (reverse bndrs) in - foldl (flip $ uncurry ForAllCo) - (Refl r $ mkInvForAllTys (reverse (map fst refls_rev'd)) ty) - non_refls_rev'd -mkForAllCos bndrs co = foldr (uncurry ForAllCo) co bndrs + foldl' (flip $ uncurry mkForAllCo_NoRefl) + (mkReflCo r (mkTyCoInvForAllTys (reverse (map fst refls_rev'd)) ty)) + non_refls_rev'd + | otherwise + = foldr (uncurry mkForAllCo_NoRefl) co bndrs --- | Make a Coercion quantified over a type variable; +-- | Make a Coercion quantified over a type/coercion variable; -- the variable has the same type in both sides of the coercion -mkHomoForAllCos :: [TyVar] -> Coercion -> Coercion -mkHomoForAllCos tvs (Refl r ty) - = Refl r (mkInvForAllTys tvs ty) -mkHomoForAllCos tvs ty = mkHomoForAllCos_NoRefl tvs ty - --- | Like 'mkHomoForAllCos', but doesn't check if the inner coercion --- is reflexive. -mkHomoForAllCos_NoRefl :: [TyVar] -> Coercion -> Coercion -mkHomoForAllCos_NoRefl tvs orig_co = foldr go orig_co tvs +mkHomoForAllCos :: [TyCoVar] -> Coercion -> Coercion +mkHomoForAllCos tvs co + | Just (ty, r) <- isReflCo_maybe co + = mkReflCo r (mkTyCoInvForAllTys tvs ty) + | otherwise + = mkHomoForAllCos_NoRefl tvs co + +-- | Like 'mkHomoForAllCos', but the inner coercion shouldn't be an obvious +-- reflexive coercion. For example, it is guaranteed in 'mkHomoForAllCos'. +mkHomoForAllCos_NoRefl :: [TyCoVar] -> Coercion -> Coercion +mkHomoForAllCos_NoRefl tvs orig_co + = ASSERT( not (isReflCo orig_co)) + foldr go orig_co tvs where - go tv co = ForAllCo tv (mkNomReflCo (tyVarKind tv)) co + go tv co = mkForAllCo_NoRefl tv (mkNomReflCo (varType tv)) co mkCoVarCo :: CoVar -> Coercion -- cv :: s ~# t @@ -794,7 +821,7 @@ mkAxInstCo role ax index tys cos = splitAt arity rtys ax_role = coAxiomRole ax --- worker function; just checks to see if it should produce Refl +-- worker function mkAxiomInstCo :: CoAxiom Branched -> BranchIndex -> [Coercion] -> Coercion mkAxiomInstCo ax index args = ASSERT( args `lengthIs` coAxiomArity ax index ) @@ -855,9 +882,8 @@ mkUnsafeCo role ty1 ty2 = mkUnivCo UnsafeCoerceProv role ty1 ty2 -- | Make a coercion from a coercion hole -mkHoleCo :: CoercionHole -> Role - -> Type -> Type -> Coercion -mkHoleCo h r t1 t2 = mkUnivCo (HoleProv h) r t1 t2 +mkHoleCo :: CoercionHole -> Coercion +mkHoleCo h = HoleCo h -- | Make a universal coercion between two arbitrary types. mkUnivCo :: UnivCoProvenance @@ -866,7 +892,7 @@ mkUnivCo :: UnivCoProvenance -> Type -- ^ t2 :: k2 -> Coercion -- ^ :: t1 ~r t2 mkUnivCo prov role ty1 ty2 - | ty1 `eqType` ty2 = Refl role ty1 + | ty1 `eqType` ty2 = mkReflCo role ty1 | otherwise = UnivCo prov role ty1 ty2 -- | Create a symmetric version of the given 'Coercion' that asserts @@ -876,7 +902,7 @@ mkSymCo :: Coercion -> Coercion -- Do a few simple optimizations, but don't bother pushing occurrences -- of symmetry to the leaves; the optimizer will take care of that. -mkSymCo co@(Refl {}) = co +mkSymCo co | isReflCo co = co mkSymCo (SymCo co) = co mkSymCo (SubCo (SymCo co)) = SubCo co mkSymCo co = SymCo co @@ -884,101 +910,193 @@ mkSymCo co = SymCo co -- | Create a new 'Coercion' by composing the two given 'Coercion's transitively. -- (co1 ; co2) mkTransCo :: Coercion -> Coercion -> Coercion -mkTransCo co1 (Refl {}) = co1 -mkTransCo (Refl {}) co2 = co2 -mkTransCo co1 co2 = TransCo co1 co2 - --- the Role is the desired one. It is the caller's responsibility to make --- sure this request is reasonable -mkNthCoRole :: Role -> Int -> Coercion -> Coercion -mkNthCoRole role n co - = downgradeRole role nth_role $ nth_co +mkTransCo co1 co2 | isReflCo co1 = co2 + | isReflCo co2 = co1 +mkTransCo (GRefl r t1 (MCo co1)) (GRefl _ _ (MCo co2)) + = GRefl r t1 (MCo $ mkTransCo co1 co2) +mkTransCo co1 co2 = TransCo co1 co2 + +mkNthCo :: HasDebugCallStack + => Role -- the role of the coercion you're creating + -> Int + -> Coercion + -> Coercion +mkNthCo r n co + = ASSERT2( good_call, bad_call_msg ) + go r n co where - nth_co = mkNthCo n co - nth_role = coercionRole nth_co - -mkNthCo :: Int -> Coercion -> Coercion -mkNthCo 0 (Refl _ ty) - | Just (tv, _) <- splitForAllTy_maybe ty - = Refl Nominal (tyVarKind tv) -mkNthCo n (Refl r ty) - = ASSERT2( ok_tc_app ty n, ppr n $$ ppr ty ) - mkReflCo r' (tyConAppArgN n ty) - where tc = tyConAppTyCon ty - r' = nthRole r tc n - - ok_tc_app :: Type -> Int -> Bool - ok_tc_app ty n - | Just (_, tys) <- splitTyConApp_maybe ty - = tys `lengthExceeds` n - | isForAllTy ty -- nth:0 pulls out a kind coercion from a hetero forall - = n == 0 - | otherwise - = False - -mkNthCo 0 (ForAllCo _ kind_co _) = kind_co - -- If co :: (forall a1:k1. t1) ~ (forall a2:k2. t2) - -- then (nth 0 co :: k1 ~ k2) - -mkNthCo n co@(FunCo _ arg res) - -- See Note [Function coercions] - -- If FunCo _ arg_co res_co :: (s1:TYPE sk1 -> s2:TYPE sk2) - -- ~ (t1:TYPE tk1 -> t2:TYPE tk2) - -- Then we want to behave as if co was - -- TyConAppCo argk_co resk_co arg_co res_co - -- where - -- argk_co :: sk1 ~ tk1 = mkNthCo 0 (mkKindCo arg_co) - -- resk_co :: sk2 ~ tk2 = mkNthCo 0 (mkKindCo res_co) - -- i.e. mkRuntimeRepCo - = case n of - 0 -> mkRuntimeRepCo arg - 1 -> mkRuntimeRepCo res - 2 -> arg - 3 -> res - _ -> pprPanic "mkNthCo(FunCo)" (ppr n $$ ppr co) - -mkNthCo n (TyConAppCo _ _ arg_cos) = arg_cos `getNth` n - -mkNthCo n co = NthCo n co + Pair ty1 ty2 = coercionKind co + + go r 0 co + | Just (ty, _) <- isReflCo_maybe co + , Just (tv, _) <- splitForAllTy_maybe ty + = -- works for both tyvar and covar + ASSERT( r == Nominal ) + mkNomReflCo (varType tv) + + go r n co + | Just (ty, r0) <- isReflCo_maybe co + , let tc = tyConAppTyCon ty + = ASSERT2( ok_tc_app ty n, ppr n $$ ppr ty ) + ASSERT( nthRole r0 tc n == r ) + mkReflCo r (tyConAppArgN n ty) + where ok_tc_app :: Type -> Int -> Bool + ok_tc_app ty n + | Just (_, tys) <- splitTyConApp_maybe ty + = tys `lengthExceeds` n + | isForAllTy ty -- nth:0 pulls out a kind coercion from a hetero forall + = n == 0 + | otherwise + = False + + go r 0 (ForAllCo _ kind_co _) + = ASSERT( r == Nominal ) + kind_co + -- If co :: (forall a1:k1. t1) ~ (forall a2:k2. t2) + -- then (nth 0 co :: k1 ~N k2) + -- If co :: (forall a1:t1 ~ t2. t1) ~ (forall a2:t3 ~ t4. t2) + -- then (nth 0 co :: (t1 ~ t2) ~N (t3 ~ t4)) + + go r n co@(FunCo r0 arg res) + -- See Note [Function coercions] + -- If FunCo _ arg_co res_co :: (s1:TYPE sk1 -> s2:TYPE sk2) + -- ~ (t1:TYPE tk1 -> t2:TYPE tk2) + -- Then we want to behave as if co was + -- TyConAppCo argk_co resk_co arg_co res_co + -- where + -- argk_co :: sk1 ~ tk1 = mkNthCo 0 (mkKindCo arg_co) + -- resk_co :: sk2 ~ tk2 = mkNthCo 0 (mkKindCo res_co) + -- i.e. mkRuntimeRepCo + = case n of + 0 -> ASSERT( r == Nominal ) mkRuntimeRepCo arg + 1 -> ASSERT( r == Nominal ) mkRuntimeRepCo res + 2 -> ASSERT( r == r0 ) arg + 3 -> ASSERT( r == r0 ) res + _ -> pprPanic "mkNthCo(FunCo)" (ppr n $$ ppr co) + + go r n (TyConAppCo r0 tc arg_cos) = ASSERT2( r == nthRole r0 tc n + , (vcat [ ppr tc + , ppr arg_cos + , ppr r0 + , ppr n + , ppr r ]) ) + arg_cos `getNth` n + + go r n co = + NthCo r n co + + -- Assertion checking + bad_call_msg = vcat [ text "Coercion =" <+> ppr co + , text "LHS ty =" <+> ppr ty1 + , text "RHS ty =" <+> ppr ty2 + , text "n =" <+> ppr n, text "r =" <+> ppr r + , text "coercion role =" <+> ppr (coercionRole co) ] + good_call + -- If the Coercion passed in is between forall-types, then the Int must + -- be 0 and the role must be Nominal. + | Just (_tv1, _) <- splitForAllTy_maybe ty1 + , Just (_tv2, _) <- splitForAllTy_maybe ty2 + = n == 0 && r == Nominal + + -- If the Coercion passed in is between T tys and T tys', then the Int + -- must be less than the length of tys/tys' (which must be the same + -- lengths). + -- + -- If the role of the Coercion is nominal, then the role passed in must + -- be nominal. If the role of the Coercion is representational, then the + -- role passed in must be tyConRolesRepresentational T !! n. If the role + -- of the Coercion is Phantom, then the role passed in must be Phantom. + -- + -- See also Note [NthCo Cached Roles] if you're wondering why it's + -- blaringly obvious that we should be *computing* this role instead of + -- passing it in. + | Just (tc1, tys1) <- splitTyConApp_maybe ty1 + , Just (tc2, tys2) <- splitTyConApp_maybe ty2 + , tc1 == tc2 + = let len1 = length tys1 + len2 = length tys2 + good_role = case coercionRole co of + Nominal -> r == Nominal + Representational -> r == (tyConRolesRepresentational tc1 !! n) + Phantom -> r == Phantom + in len1 == len2 && n < len1 && good_role + + | otherwise + = True + + + +-- | If you're about to call @mkNthCo r n co@, then @r@ should be +-- whatever @nthCoRole n co@ returns. +nthCoRole :: Int -> Coercion -> Role +nthCoRole n co + | Just (tc, _) <- splitTyConApp_maybe lty + = nthRole r tc n + + | Just _ <- splitForAllTy_maybe lty + = Nominal + + | otherwise + = pprPanic "nthCoRole" (ppr co) + + where + (Pair lty _, r) = coercionKindRole co mkLRCo :: LeftOrRight -> Coercion -> Coercion -mkLRCo lr (Refl eq ty) = Refl eq (pickLR lr (splitAppTy ty)) -mkLRCo lr co = LRCo lr co +mkLRCo lr co + | Just (ty, eq) <- isReflCo_maybe co + = mkReflCo eq (pickLR lr (splitAppTy ty)) + | otherwise + = LRCo lr co -- | Instantiates a 'Coercion'. mkInstCo :: Coercion -> Coercion -> Coercion -mkInstCo (ForAllCo tv _kind_co body_co) (Refl _ arg) - = substCoWithUnchecked [tv] [arg] body_co +mkInstCo (ForAllCo tcv _kind_co body_co) co + | Just (arg, _) <- isReflCo_maybe co + -- works for both tyvar and covar + = substCoUnchecked (zipTCvSubst [tcv] [arg]) body_co mkInstCo co arg = InstCo co arg --- This could work harder to produce Refl coercions, but that would be --- quite inefficient. Seems better not to try. -mkCoherenceCo :: Coercion -> Coercion -> Coercion -mkCoherenceCo co1 (Refl {}) = co1 -mkCoherenceCo (CoherenceCo co1 co2) co3 - = CoherenceCo co1 (co2 `mkTransCo` co3) -mkCoherenceCo co1 co2 = CoherenceCo co1 co2 - --- | A CoherenceCo c1 c2 applies the coercion c2 to the left-hand type --- in the kind of c1. This function uses sym to get the coercion on the --- right-hand type of c1. Thus, if c1 :: s ~ t, then mkCoherenceRightCo c1 c2 --- has the kind (s ~ (t |> c2)) down through type constructors. --- The second coercion must be representational. -mkCoherenceRightCo :: Coercion -> Coercion -> Coercion -mkCoherenceRightCo c1 c2 = mkSymCo (mkCoherenceCo (mkSymCo c1) c2) - --- | An explicitly directed synonym of mkCoherenceCo. The second --- coercion must be representational. -mkCoherenceLeftCo :: Coercion -> Coercion -> Coercion -mkCoherenceLeftCo = mkCoherenceCo - -infixl 5 `mkCoherenceCo` -infixl 5 `mkCoherenceRightCo` -infixl 5 `mkCoherenceLeftCo` +-- | Given @ty :: k1@, @co :: k1 ~ k2@, +-- produces @co' :: ty ~r (ty |> co)@ +mkGReflRightCo :: Role -> Type -> CoercionN -> Coercion +mkGReflRightCo r ty co + | isGReflCo co = mkReflCo r ty + -- the kinds of @k1@ and @k2@ are the same, thus @isGReflCo@ + -- instead of @isReflCo@ + | otherwise = GRefl r ty (MCo co) + +-- | Given @ty :: k1@, @co :: k1 ~ k2@, +-- produces @co' :: (ty |> co) ~r ty@ +mkGReflLeftCo :: Role -> Type -> CoercionN -> Coercion +mkGReflLeftCo r ty co + | isGReflCo co = mkReflCo r ty + -- the kinds of @k1@ and @k2@ are the same, thus @isGReflCo@ + -- instead of @isReflCo@ + | otherwise = mkSymCo $ GRefl r ty (MCo co) + +-- | Given @ty :: k1@, @co :: k1 ~ k2@, @co2:: ty ~ ty'@, +-- produces @co' :: (ty |> co) ~r ty' +-- It is not only a utility function, but it saves allocation when co +-- is a GRefl coercion. +mkCoherenceLeftCo :: Role -> Type -> CoercionN -> Coercion -> Coercion +mkCoherenceLeftCo r ty co co2 + | isGReflCo co = co2 + | otherwise = (mkSymCo $ GRefl r ty (MCo co)) `mkTransCo` co2 + +-- | Given @ty :: k1@, @co :: k1 ~ k2@, @co2:: ty' ~ ty@, +-- produces @co' :: ty' ~r (ty |> co) +-- It is not only a utility function, but it saves allocation when co +-- is a GRefl coercion. +mkCoherenceRightCo :: Role -> Type -> CoercionN -> Coercion -> Coercion +mkCoherenceRightCo r ty co co2 + | isGReflCo co = co2 + | otherwise = co2 `mkTransCo` GRefl r ty (MCo co) -- | Given @co :: (a :: k) ~ (b :: k')@ produce @co' :: k ~ k'@. mkKindCo :: Coercion -> Coercion -mkKindCo (Refl _ ty) = Refl Nominal (typeKind ty) +mkKindCo co | Just (ty, _) <- isReflCo_maybe co = Refl (typeKind ty) +mkKindCo (GRefl _ _ (MCo co)) = co mkKindCo (UnivCo (PhantomProv h) _ _ _) = h mkKindCo (UnivCo (ProofIrrelProv h) _ _ _) = h mkKindCo co @@ -989,13 +1107,15 @@ mkKindCo co , let tk1 = typeKind ty1 tk2 = typeKind ty2 , tk1 `eqType` tk2 - = Refl Nominal tk1 + = Refl tk1 | otherwise = KindCo co --- input coercion is Nominal; see also Note [Role twiddling functions] mkSubCo :: Coercion -> Coercion -mkSubCo (Refl Nominal ty) = Refl Representational ty +-- Input coercion is Nominal, result is Representational +-- see also Note [Role twiddling functions] +mkSubCo (Refl ty) = GRefl Representational ty MRefl +mkSubCo (GRefl Nominal ty co) = GRefl Representational ty co mkSubCo (TyConAppCo Nominal tc cos) = TyConAppCo Representational tc (applyRoles tc cos) mkSubCo (FunCo Nominal arg res) @@ -1011,12 +1131,16 @@ downgradeRole_maybe :: Role -- ^ desired role -> Coercion -> Maybe Coercion -- In (downgradeRole_maybe dr cr co) it's a precondition that -- cr = coercionRole co -downgradeRole_maybe Representational Nominal co = Just (mkSubCo co) -downgradeRole_maybe Nominal Representational _ = Nothing -downgradeRole_maybe Phantom Phantom co = Just co -downgradeRole_maybe Phantom _ co = Just (toPhantomCo co) -downgradeRole_maybe _ Phantom _ = Nothing -downgradeRole_maybe _ _ co = Just co + +downgradeRole_maybe Nominal Nominal co = Just co +downgradeRole_maybe Nominal _ _ = Nothing + +downgradeRole_maybe Representational Nominal co = Just (mkSubCo co) +downgradeRole_maybe Representational Representational co = Just co +downgradeRole_maybe Representational Phantom _ = Nothing + +downgradeRole_maybe Phantom Phantom co = Just co +downgradeRole_maybe Phantom _ co = Just (toPhantomCo co) -- | Like 'downgradeRole_maybe', but panics if the change isn't a downgrade. -- See Note [Role twiddling functions] @@ -1047,9 +1171,10 @@ mkProofIrrelCo :: Role -- ^ role of the created coercion, "r" -- if the two coercion prove the same fact, I just don't care what -- the individual coercions are. -mkProofIrrelCo r (Refl {}) g _ = Refl r (CoercionTy g) -mkProofIrrelCo r kco g1 g2 = mkUnivCo (ProofIrrelProv kco) r - (mkCoercionTy g1) (mkCoercionTy g2) +mkProofIrrelCo r co g _ | isGReflCo co = mkReflCo r (mkCoercionTy g) + -- kco is a kind coercion, thus @isGReflCo@ rather than @isReflCo@ +mkProofIrrelCo r kco g1 g2 = mkUnivCo (ProofIrrelProv kco) r + (mkCoercionTy g1) (mkCoercionTy g2) {- %************************************************************************ @@ -1061,41 +1186,44 @@ mkProofIrrelCo r kco g1 g2 = mkUnivCo (ProofIrrelProv kco) r -- | Converts a coercion to be nominal, if possible. -- See Note [Role twiddling functions] -setNominalRole_maybe :: Coercion -> Maybe Coercion -setNominalRole_maybe co - | Nominal <- coercionRole co = Just co -setNominalRole_maybe (SubCo co) = Just co -setNominalRole_maybe (Refl _ ty) = Just $ Refl Nominal ty -setNominalRole_maybe (TyConAppCo Representational tc cos) - = do { cos' <- mapM setNominalRole_maybe cos - ; return $ TyConAppCo Nominal tc cos' } -setNominalRole_maybe (FunCo Representational co1 co2) - = do { co1' <- setNominalRole_maybe co1 - ; co2' <- setNominalRole_maybe co2 - ; return $ FunCo Nominal co1' co2' - } -setNominalRole_maybe (SymCo co) - = SymCo <$> setNominalRole_maybe co -setNominalRole_maybe (TransCo co1 co2) - = TransCo <$> setNominalRole_maybe co1 <*> setNominalRole_maybe co2 -setNominalRole_maybe (AppCo co1 co2) - = AppCo <$> setNominalRole_maybe co1 <*> pure co2 -setNominalRole_maybe (ForAllCo tv kind_co co) - = ForAllCo tv kind_co <$> setNominalRole_maybe co -setNominalRole_maybe (NthCo n co) - = NthCo n <$> setNominalRole_maybe co -setNominalRole_maybe (InstCo co arg) - = InstCo <$> setNominalRole_maybe co <*> pure arg -setNominalRole_maybe (CoherenceCo co1 co2) - = CoherenceCo <$> setNominalRole_maybe co1 <*> pure co2 -setNominalRole_maybe (UnivCo prov _ co1 co2) - | case prov of UnsafeCoerceProv -> True -- it's always unsafe - PhantomProv _ -> False -- should always be phantom - ProofIrrelProv _ -> True -- it's always safe - PluginProv _ -> False -- who knows? This choice is conservative. - HoleProv _ -> False -- no no no. - = Just $ UnivCo prov Nominal co1 co2 -setNominalRole_maybe _ = Nothing +setNominalRole_maybe :: Role -- of input coercion + -> Coercion -> Maybe Coercion +setNominalRole_maybe r co + | r == Nominal = Just co + | otherwise = setNominalRole_maybe_helper co + where + setNominalRole_maybe_helper (SubCo co) = Just co + setNominalRole_maybe_helper co@(Refl _) = Just co + setNominalRole_maybe_helper (GRefl _ ty co) = Just $ GRefl Nominal ty co + setNominalRole_maybe_helper (TyConAppCo Representational tc cos) + = do { cos' <- zipWithM setNominalRole_maybe (tyConRolesX Representational tc) cos + ; return $ TyConAppCo Nominal tc cos' } + setNominalRole_maybe_helper (FunCo Representational co1 co2) + = do { co1' <- setNominalRole_maybe Representational co1 + ; co2' <- setNominalRole_maybe Representational co2 + ; return $ FunCo Nominal co1' co2' + } + setNominalRole_maybe_helper (SymCo co) + = SymCo <$> setNominalRole_maybe_helper co + setNominalRole_maybe_helper (TransCo co1 co2) + = TransCo <$> setNominalRole_maybe_helper co1 <*> setNominalRole_maybe_helper co2 + setNominalRole_maybe_helper (AppCo co1 co2) + = AppCo <$> setNominalRole_maybe_helper co1 <*> pure co2 + setNominalRole_maybe_helper (ForAllCo tv kind_co co) + = ForAllCo tv kind_co <$> setNominalRole_maybe_helper co + setNominalRole_maybe_helper (NthCo _r n co) + -- NB, this case recurses via setNominalRole_maybe, not + -- setNominalRole_maybe_helper! + = NthCo Nominal n <$> setNominalRole_maybe (coercionRole co) co + setNominalRole_maybe_helper (InstCo co arg) + = InstCo <$> setNominalRole_maybe_helper co <*> pure arg + setNominalRole_maybe_helper (UnivCo prov _ co1 co2) + | case prov of UnsafeCoerceProv -> True -- it's always unsafe + PhantomProv _ -> False -- should always be phantom + ProofIrrelProv _ -> True -- it's always safe + PluginProv _ -> False -- who knows? This choice is conservative. + = Just $ UnivCo prov Nominal co1 co2 + setNominalRole_maybe_helper _ = Nothing -- | Make a phantom coercion between two types. The coercion passed -- in must be a nominal coercion between the kinds of the @@ -1104,14 +1232,6 @@ mkPhantomCo :: Coercion -> Type -> Type -> Coercion mkPhantomCo h t1 t2 = mkUnivCo (PhantomProv h) Phantom t1 t2 --- | Make a phantom coercion between two types of the same kind. -mkHomoPhantomCo :: Type -> Type -> Coercion -mkHomoPhantomCo t1 t2 - = ASSERT( k1 `eqType` typeKind t2 ) - mkPhantomCo (mkNomReflCo k1) t1 t2 - where - k1 = typeKind t1 - -- takes any coercion and turns it into a Phantom coercion toPhantomCo :: Coercion -> Coercion toPhantomCo co @@ -1124,7 +1244,7 @@ applyRoles tc cos = zipWith (\r -> downgradeRole r Nominal) (tyConRolesRepresentational tc) cos -- the Role parameter is the Role of the TyConAppCo --- defined here because this is intimiately concerned with the implementation +-- defined here because this is intimately concerned with the implementation -- of TyConAppCo tyConRolesX :: Role -> TyCon -> [Role] tyConRolesX Representational tc = tyConRolesRepresentational tc @@ -1152,7 +1272,7 @@ ltRole Nominal _ = True -- | like mkKindCo, but aggressively & recursively optimizes to avoid using -- a KindCo constructor. The output role is nominal. -promoteCoercion :: Coercion -> Coercion +promoteCoercion :: Coercion -> CoercionN -- First cases handles anything that should yield refl. promoteCoercion co = case co of @@ -1163,8 +1283,13 @@ promoteCoercion co = case co of -- The ASSERT( False )s throughout -- are these cases explicitly, but they should never fire. - Refl _ ty -> ASSERT( False ) - mkNomReflCo (typeKind ty) + Refl _ -> ASSERT( False ) + mkNomReflCo ki1 + + GRefl _ _ MRefl -> ASSERT( False ) + mkNomReflCo ki1 + + GRefl _ _ (MCo co) -> co TyConAppCo _ tc args | Just co' <- instCoercions (mkNomReflCo (tyConKind tc)) args @@ -1179,28 +1304,28 @@ promoteCoercion co = case co of | otherwise -> mkKindCo co - ForAllCo _ _ g + ForAllCo tv _ g + | isTyVar tv -> promoteCoercion g - FunCo _ _ _ - -> mkNomReflCo liftedTypeKind + ForAllCo _ _ _ + -> ASSERT( False ) + mkNomReflCo liftedTypeKind + -- See Note [Weird typing rule for ForAllTy] in Type - CoVarCo {} - -> mkKindCo co + FunCo _ _ _ + -> ASSERT( False ) + mkNomReflCo liftedTypeKind - AxiomInstCo {} - -> mkKindCo co + CoVarCo {} -> mkKindCo co + HoleCo {} -> mkKindCo co + AxiomInstCo {} -> mkKindCo co + AxiomRuleCo {} -> mkKindCo co - UnivCo UnsafeCoerceProv _ t1 t2 - -> mkUnsafeCo Nominal (typeKind t1) (typeKind t2) - UnivCo (PhantomProv kco) _ _ _ - -> kco - UnivCo (ProofIrrelProv kco) _ _ _ - -> kco - UnivCo (PluginProv _) _ _ _ - -> mkKindCo co - UnivCo (HoleProv _) _ _ _ - -> mkKindCo co + UnivCo UnsafeCoerceProv _ t1 t2 -> mkUnsafeCo Nominal (typeKind t1) (typeKind t2) + UnivCo (PhantomProv kco) _ _ _ -> kco + UnivCo (ProofIrrelProv kco) _ _ _ -> kco + UnivCo (PluginProv _) _ _ _ -> mkKindCo co SymCo g -> mkSymCo (promoteCoercion g) @@ -1208,7 +1333,7 @@ promoteCoercion co = case co of TransCo co1 co2 -> mkTransCo (promoteCoercion co1) (promoteCoercion co2) - NthCo n co1 + NthCo _ n co1 | Just (_, args) <- splitTyConAppCo_maybe co1 , args `lengthExceeds` n -> promoteCoercion (args !! n) @@ -1230,10 +1355,13 @@ promoteCoercion co = case co of -> mkKindCo co InstCo g _ - -> promoteCoercion g - - CoherenceCo g h - -> mkSymCo h `mkTransCo` promoteCoercion g + | isForAllTy_ty ty1 + -> ASSERT( isForAllTy_ty ty2 ) + promoteCoercion g + | otherwise + -> ASSERT( False) + mkNomReflCo liftedTypeKind + -- See Note [Weird typing rule for ForAllTy] in Type KindCo _ -> ASSERT( False ) @@ -1242,9 +1370,6 @@ promoteCoercion co = case co of SubCo g -> promoteCoercion g - AxiomRuleCo {} - -> mkKindCo co - where Pair ty1 ty2 = coercionKind co ki1 = typeKind ty1 @@ -1254,22 +1379,28 @@ promoteCoercion co = case co of -- where @g' = promoteCoercion (h w)@. -- fails if this is not possible, if @g@ coerces between a forall and an -> -- or if second parameter has a representational role and can't be used --- with an InstCo. The result role matches is representational. -instCoercion :: Pair Type -- type of the first coercion - -> Coercion -- ^ must be nominal +-- with an InstCo. +instCoercion :: Pair Type -- g :: lty ~ rty + -> CoercionN -- ^ must be nominal -> Coercion - -> Maybe Coercion + -> Maybe CoercionN instCoercion (Pair lty rty) g w - | isForAllTy lty && isForAllTy rty - , Just w' <- setNominalRole_maybe w + | (isForAllTy_ty lty && isForAllTy_ty rty) + || (isForAllTy_co lty && isForAllTy_co rty) + , Just w' <- setNominalRole_maybe (coercionRole w) w + -- g :: (forall t1. t2) ~ (forall t1. t3) + -- w :: s1 ~ s2 + -- returns mkInstCo g w' :: t2 [t1 |-> s1 ] ~ t3 [t1 |-> s2] = Just $ mkInstCo g w' | isFunTy lty && isFunTy rty - = Just $ mkNthCo 3 g -- extract result type, which is the 4th argument to (->) + -- g :: (t1 -> t2) ~ (t3 -> t4) + -- returns t2 ~ t4 + = Just $ mkNthCo Nominal 3 g -- extract result type, which is the 4th argument to (->) | otherwise -- one forall, one funty... = Nothing - where -instCoercions :: Coercion -> [Coercion] -> Maybe Coercion +-- | Repeated use of 'instCoercion' +instCoercions :: CoercionN -> [Coercion] -> Maybe CoercionN instCoercions g ws = let arg_ty_pairs = map coercionKind ws in snd <$> foldM go (coercionKind g, g) (zip arg_ty_pairs ws) @@ -1281,11 +1412,24 @@ instCoercions g ws ; return (piResultTy <$> g_tys <*> w_tys, g') } -- | Creates a new coercion with both of its types casted by different casts --- castCoercionKind g h1 h2, where g :: t1 ~ t2, has type (t1 |> h1) ~ (t2 |> h2) --- The second and third coercions must be nominal. -castCoercionKind :: Coercion -> Coercion -> Coercion -> Coercion -castCoercionKind g h1 h2 - = g `mkCoherenceLeftCo` h1 `mkCoherenceRightCo` h2 +-- @castCoercionKind g r t1 t2 h1 h2@, where @g :: t1 ~r t2@, +-- has type @(t1 |> h1) ~r (t2 |> h2)@. +-- @h1@ and @h2@ must be nominal. +castCoercionKind :: Coercion -> Role -> Type -> Type + -> CoercionN -> CoercionN -> Coercion +castCoercionKind g r t1 t2 h1 h2 + = mkCoherenceRightCo r t2 h2 (mkCoherenceLeftCo r t1 h1 g) + +-- | Creates a new coercion with both of its types casted by different casts +-- @castCoercionKind g h1 h2@, where @g :: t1 ~r t2@, +-- has type @(t1 |> h1) ~r (t2 |> h2)@. +-- @h1@ and @h2@ must be nominal. +-- It calls @coercionKindRole@, so it's quite inefficient (which 'I' stands for) +-- Use @castCoercionKind@ instead if @t1@, @t2@, and @r@ are known beforehand. +castCoercionKindI :: Coercion -> CoercionN -> CoercionN -> Coercion +castCoercionKindI g h1 h2 + = mkCoherenceRightCo r t2 h2 (mkCoherenceLeftCo r t1 h1 g) + where (Pair t1 t2, r) = coercionKindRole g -- See note [Newtype coercions] in TyCon @@ -1293,27 +1437,38 @@ mkPiCos :: Role -> [Var] -> Coercion -> Coercion mkPiCos r vs co = foldr (mkPiCo r) co vs -- | Make a forall 'Coercion', where both types related by the coercion --- are quantified over the same type variable. +-- are quantified over the same variable. mkPiCo :: Role -> Var -> Coercion -> Coercion mkPiCo r v co | isTyVar v = mkHomoForAllCos [v] co + | isCoVar v = ASSERT( not (v `elemVarSet` tyCoVarsOfCo co) ) + -- We didn't call mkForAllCo here because if v does not appear + -- in co, the argement coercion will be nominal. But here we + -- want it to be r. It is only called in 'mkPiCos', which is + -- only used in SimplUtils, where we are sure for + -- now (Aug 2018) v won't occur in co. + mkFunCo r (mkReflCo r (varType v)) co | otherwise = mkFunCo r (mkReflCo r (varType v)) co --- The second coercion is sometimes lifted (~) and sometimes unlifted (~#). --- So, we have to make sure to supply the right parameter to decomposeCo. --- mkCoCast (c :: s1 ~# t1) (g :: (s1 ~# s2) ~# (t1 ~# t2)) :: s2 ~# t2 --- Both coercions *must* have the same role. -mkCoCast :: Coercion -> Coercion -> Coercion +-- mkCoCast (c :: s1 ~?r t1) (g :: (s1 ~?r t1) ~#R (s2 ~?r t2)) :: s2 ~?r t2 +-- The first coercion might be lifted or unlifted; thus the ~? above +-- Lifted and unlifted equalities take different numbers of arguments, +-- so we have to make sure to supply the right parameter to decomposeCo. +-- Also, note that the role of the first coercion is the same as the role of +-- the equalities related by the second coercion. The second coercion is +-- itself always representational. +mkCoCast :: Coercion -> CoercionR -> Coercion mkCoCast c g + | (g2:g1:_) <- reverse co_list = mkSymCo g1 `mkTransCo` c `mkTransCo` g2 + + | otherwise + = pprPanic "mkCoCast" (ppr g $$ ppr (coercionKind g)) where - -- g :: (s1 ~# s2) ~# (t1 ~# t2) - -- g1 :: s1 ~# t1 - -- g2 :: s2 ~# t2 - (_, args) = splitTyConApp (pFst $ coercionKind g) - n_args = length args - co_list = decomposeCo n_args g - g1 = co_list `getNth` (n_args - 2) - g2 = co_list `getNth` (n_args - 1) + -- g :: (s1 ~# t1) ~# (s2 ~# t2) + -- g1 :: s1 ~# s2 + -- g2 :: t1 ~# t2 + (tc, _) = splitTyConApp (pFst $ coercionKind g) + co_list = decomposeCo (tyConArity tc) g (tyConRolesRepresentational tc) {- %************************************************************************ @@ -1468,8 +1623,8 @@ eqCoercionX env = eqTypeX env `on` coercionType Note [Lifting coercions over types: liftCoSubst] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The KPUSH rule deals with this situation - data T a = MkK (a -> Maybe a) - g :: T t1 ~ K t2 + data T a = K (a -> Maybe a) + g :: T t1 ~ T t2 x :: t1 -> Maybe t1 case (K @t1 x) |> g of @@ -1491,6 +1646,40 @@ thus giving *coercion*. This is what liftCoSubst does. In the presence of kind coercions, this is a bit of a hairy operation. So, we refer you to the paper introducing kind coercions, available at www.cis.upenn.edu/~sweirich/papers/fckinds-extended.pdf + +Note [extendLiftingContextEx] +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Consider we have datatype + K :: \/k. \/a::k. P -> T k -- P be some type + g :: T k1 ~ T k2 + + case (K @k1 @t1 x) |> g of + K y -> rhs + +We want to push the coercion inside the constructor application. +We first get the coercion mapped by the universal type variable k: + lc = k |-> Nth 0 g :: k1~k2 + +Here, the important point is that the kind of a is coerced, and P might be +dependent on the existential type variable a. +Thus we first get the coercion of a's kind + g2 = liftCoSubst lc k :: k1 ~ k2 + +Then we store a new mapping into the lifting context + lc2 = a |-> (t1 ~ t1 |> g2), lc + +So later when we can correctly deal with the argument type P + liftCoSubst lc2 P :: P [k|->k1][a|->t1] ~ P[k|->k2][a |-> (t1|>g2)] + +This is exactly what extendLiftingContextEx does. +* For each (tyvar:k, ty) pair, we product the mapping + tyvar |-> (ty ~ ty |> (liftCoSubst lc k)) +* For each (covar:s1~s2, ty) pair, we produce the mapping + covar |-> (co ~ co') + co' = Sym (liftCoSubst lc s1) ;; covar ;; liftCoSubst lc s2 :: s1'~s2' + +This follows the lifting context extension definition in the +"FC with Explicit Kind Equality" paper. -} -- ---------------------------------------------------- @@ -1508,21 +1697,21 @@ instance Outputable LiftingContext where type LiftCoEnv = VarEnv Coercion -- Maps *type variables* to *coercions*. -- That's the whole point of this function! + -- Also maps coercion variables to ProofIrrelCos. -- like liftCoSubstWith, but allows for existentially-bound types as well liftCoSubstWithEx :: Role -- desired role for output coercion -> [TyVar] -- universally quantified tyvars -> [Coercion] -- coercions to substitute for those - -> [TyVar] -- existentially quantified tyvars - -> [Type] -- types to be bound to ex vars + -> [TyCoVar] -- existentially quantified tycovars + -> [Type] -- types and coercions to be bound to ex vars -> (Type -> Coercion, [Type]) -- (lifting function, converted ex args) liftCoSubstWithEx role univs omegas exs rhos = let theta = mkLiftingContext (zipEqual "liftCoSubstWithExU" univs omegas) psi = extendLiftingContextEx theta (zipEqual "liftCoSubstWithExX" exs rhos) - in (ty_co_subst psi role, substTyVars (lcSubstRight psi) exs) + in (ty_co_subst psi role, substTys (lcSubstRight psi) (mkTyCoVarTys exs)) liftCoSubstWith :: Role -> [TyCoVar] -> [Coercion] -> Type -> Coercion --- NB: This really can be called with CoVars, when optimising axioms. liftCoSubstWith r tvs cos ty = liftCoSubst r (mkLiftingContext $ zipEqual "liftCoSubstWith" tvs cos) ty @@ -1532,7 +1721,7 @@ liftCoSubstWith r tvs cos ty -- types of the mapped coercions in @lc@, and similar for @lc_right@. liftCoSubst :: HasDebugCallStack => Role -> LiftingContext -> Type -> Coercion liftCoSubst r lc@(LC subst env) ty - | isEmptyVarEnv env = Refl r (substTy subst ty) + | isEmptyVarEnv env = mkReflCo r (substTy subst ty) | otherwise = ty_co_subst lc r ty emptyLiftingContext :: InScopeSet -> LiftingContext @@ -1546,20 +1735,30 @@ mkLiftingContext pairs mkSubstLiftingContext :: TCvSubst -> LiftingContext mkSubstLiftingContext subst = LC subst emptyVarEnv --- | Extend a lifting context with a new /type/ mapping. +-- | Extend a lifting context with a new mapping. extendLiftingContext :: LiftingContext -- ^ original LC - -> TyVar -- ^ new variable to map... + -> TyCoVar -- ^ new variable to map... -> Coercion -- ^ ...to this lifted version -> LiftingContext + -- mappings to reflexive coercions are just substitutions extendLiftingContext (LC subst env) tv arg - = ASSERT( isTyVar tv ) - LC subst (extendVarEnv env tv arg) + | Just (ty, _) <- isReflCo_maybe arg + = LC (extendTCvSubst subst tv ty) env + | otherwise + = LC subst (extendVarEnv env tv arg) + +-- | Extend a lifting context with a new mapping, and extend the in-scope set +extendLiftingContextAndInScope :: LiftingContext -- ^ Original LC + -> TyCoVar -- ^ new variable to map... + -> Coercion -- ^ to this coercion + -> LiftingContext +extendLiftingContextAndInScope (LC subst env) tv co + = extendLiftingContext (LC (extendTCvInScopeSet subst (tyCoVarsOfCo co)) env) tv co -- | Extend a lifting context with existential-variable bindings. --- This follows the lifting context extension definition in the --- "FC with Explicit Kind Equality" paper. +-- See Note [extendLiftingContextEx] extendLiftingContextEx :: LiftingContext -- ^ original lifting context - -> [(TyVar,Type)] -- ^ ex. var / value pairs + -> [(TyCoVar,Type)] -- ^ ex. var / value pairs -> LiftingContext -- Note that this is more involved than extendLiftingContext. That function -- takes a coercion to extend with, so it's assumed that the caller has taken @@ -1569,25 +1768,47 @@ extendLiftingContextEx lc@(LC subst env) ((v,ty):rest) -- This function adds bindings for *Nominal* coercions. Why? Because it -- works with existentially bound variables, which are considered to have -- nominal roles. + | isTyVar v = let lc' = LC (subst `extendTCvInScopeSet` tyCoVarsOfType ty) - (extendVarEnv env v (mkSymCo $ mkCoherenceCo - (mkNomReflCo ty) - (ty_co_subst lc Nominal (tyVarKind v)))) + (extendVarEnv env v $ + mkGReflRightCo Nominal + ty + (ty_co_subst lc Nominal (tyVarKind v))) in extendLiftingContextEx lc' rest + | CoercionTy co <- ty + = -- co :: s1 ~r s2 + -- lift_s1 :: s1 ~r s1' + -- lift_s2 :: s2 ~r s2' + -- kco :: (s1 ~r s2) ~N (s1' ~r s2') + ASSERT( isCoVar v ) + let (_, _, s1, s2, r) = coVarKindsTypesRole v + lift_s1 = ty_co_subst lc r s1 + lift_s2 = ty_co_subst lc r s2 + kco = mkTyConAppCo Nominal (equalityTyCon r) + [ mkKindCo lift_s1, mkKindCo lift_s2 + , lift_s1 , lift_s2 ] + lc' = LC (subst `extendTCvInScopeSet` tyCoVarsOfCo co) + (extendVarEnv env v + (mkProofIrrelCo Nominal kco co $ + (mkSymCo lift_s1) `mkTransCo` co `mkTransCo` lift_s2)) + in extendLiftingContextEx lc' rest + | otherwise + = pprPanic "extendLiftingContextEx" (ppr v <+> text "|->" <+> ppr ty) + -- | Erase the environments in a lifting context zapLiftingContext :: LiftingContext -> LiftingContext zapLiftingContext (LC subst _) = LC (zapTCvSubst subst) emptyVarEnv -- | Like 'substForAllCoBndr', but works on a lifting context -substForAllCoBndrCallbackLC :: Bool +substForAllCoBndrUsingLC :: Bool -> (Coercion -> Coercion) - -> LiftingContext -> TyVar -> Coercion - -> (LiftingContext, TyVar, Coercion) -substForAllCoBndrCallbackLC sym sco (LC subst lc_env) tv co + -> LiftingContext -> TyCoVar -> Coercion + -> (LiftingContext, TyCoVar, Coercion) +substForAllCoBndrUsingLC sym sco (LC subst lc_env) tv co = (LC subst' lc_env, tv', co') where - (subst', tv', co') = substForAllCoBndrCallback sym sco subst tv co + (subst', tv', co') = substForAllCoBndrUsing sym sco subst tv co -- | The \"lifting\" operation which substitutes coercions for type -- variables in a type to produce a coercion. @@ -1598,19 +1819,21 @@ ty_co_subst lc role ty = go role ty where go :: Role -> Type -> Coercion + go r ty | Just ty' <- coreView ty + = go r ty' go Phantom ty = lift_phantom ty go r (TyVarTy tv) = expectJust "ty_co_subst bad roles" $ liftCoSubstTyVar lc r tv go r (AppTy ty1 ty2) = mkAppCo (go r ty1) (go Nominal ty2) go r (TyConApp tc tys) = mkTyConAppCo r tc (zipWith go (tyConRolesX r tc) tys) go r (FunTy ty1 ty2) = mkFunCo r (go r ty1) (go r ty2) - go r (ForAllTy (TvBndr v _) ty) + go r (ForAllTy (Bndr v _) ty) = let (lc', v', h) = liftCoSubstVarBndr lc v in mkForAllCo v' h $! ty_co_subst lc' r ty go r ty@(LitTy {}) = ASSERT( r == Nominal ) - mkReflCo r ty - go r (CastTy ty co) = castCoercionKind (go r ty) (substLeftCo lc co) - (substRightCo lc co) + mkNomReflCo ty + go r (CastTy ty co) = castCoercionKindI (go r ty) (substLeftCo lc co) + (substRightCo lc co) go r (CoercionTy co) = mkProofIrrelCo r kco (substLeftCo lc co) (substRightCo lc co) where kco = go Nominal (coercionType co) @@ -1639,22 +1862,71 @@ liftCoSubstTyVar (LC subst env) r v = downgradeRole_maybe r (coercionRole co_arg) co_arg | otherwise - = Just $ Refl r (substTyVar subst v) + = Just $ mkReflCo r (substTyVar subst v) + +{- Note [liftCoSubstVarBndr] + +callback: + We want 'liftCoSubstVarBndrUsing' to be general enough to be reused in + FamInstEnv, therefore the input arg 'fun' returns a pair with polymophic type + in snd. + However in 'liftCoSubstVarBndr', we don't need the snd, so we use unit and + ignore the fourth componenet of the return value. + +liftCoSubstTyVarBndrUsing: + Given + forall tv:k. t + We want to get + forall (tv:k1) (kind_co :: k1 ~ k2) body_co + + We lift the kind k to get the kind_co + kind_co = ty_co_subst k :: k1 ~ k2 + + Now in the LiftingContext, we add the new mapping + tv |-> (tv :: k1) ~ ((tv |> kind_co) :: k2) + +liftCoSubstCoVarBndrUsing: + Given + forall cv:(s1 ~ s2). t + We want to get + forall (cv:s1'~s2') (kind_co :: (s1'~s2') ~ (t1 ~ t2)) body_co + + We lift s1 and s2 respectively to get + eta1 :: s1' ~ t1 + eta2 :: s2' ~ t2 + And + kind_co = TyConAppCo Nominal (~#) eta1 eta2 + + Now in the liftingContext, we add the new mapping + cv |-> (cv :: s1' ~ s2') ~ ((sym eta1;cv;eta2) :: t1 ~ t2) +-} -liftCoSubstVarBndr :: LiftingContext -> TyVar - -> (LiftingContext, TyVar, Coercion) +-- See Note [liftCoSubstVarBndr] +liftCoSubstVarBndr :: LiftingContext -> TyCoVar + -> (LiftingContext, TyCoVar, Coercion) liftCoSubstVarBndr lc tv - = let (lc', tv', h, _) = liftCoSubstVarBndrCallback callback lc tv in + = let (lc', tv', h, _) = liftCoSubstVarBndrUsing callback lc tv in (lc', tv', h) where callback lc' ty' = (ty_co_subst lc' Nominal ty', ()) -- the callback must produce a nominal coercion -liftCoSubstVarBndrCallback :: (LiftingContext -> Type -> (Coercion, a)) +liftCoSubstVarBndrUsing :: (LiftingContext -> Type -> (CoercionN, a)) + -> LiftingContext -> TyCoVar + -> (LiftingContext, TyCoVar, CoercionN, a) +liftCoSubstVarBndrUsing fun lc old_var + | isTyVar old_var + = liftCoSubstTyVarBndrUsing fun lc old_var + | otherwise + = liftCoSubstCoVarBndrUsing fun lc old_var + +-- Works for tyvar binder +liftCoSubstTyVarBndrUsing :: (LiftingContext -> Type -> (CoercionN, a)) -> LiftingContext -> TyVar - -> (LiftingContext, TyVar, Coercion, a) -liftCoSubstVarBndrCallback fun lc@(LC subst cenv) old_var - = ( LC (subst `extendTCvInScope` new_var) new_cenv + -> (LiftingContext, TyVar, CoercionN, a) +liftCoSubstTyVarBndrUsing fun lc@(LC subst cenv) old_var + = ASSERT( isTyVar old_var ) + ( LC (subst `extendTCvInScope` new_var) new_cenv , new_var, eta, stuff ) where old_kind = tyVarKind old_var @@ -1662,7 +1934,45 @@ liftCoSubstVarBndrCallback fun lc@(LC subst cenv) old_var Pair k1 _ = coercionKind eta new_var = uniqAway (getTCvInScope subst) (setVarType old_var k1) - lifted = Refl Nominal (TyVarTy new_var) + lifted = mkGReflRightCo Nominal (TyVarTy new_var) eta + -- :: new_var ~ new_var |> eta + new_cenv = extendVarEnv cenv old_var lifted + +-- Works for covar binder +liftCoSubstCoVarBndrUsing :: (LiftingContext -> Type -> (CoercionN, a)) + -> LiftingContext -> CoVar + -> (LiftingContext, CoVar, CoercionN, a) +liftCoSubstCoVarBndrUsing fun lc@(LC subst cenv) old_var + = ASSERT( isCoVar old_var ) + ( LC (subst `extendTCvInScope` new_var) new_cenv + , new_var, kind_co, stuff ) + where + old_kind = coVarKind old_var + (eta, stuff) = fun lc old_kind + Pair k1 _ = coercionKind eta + new_var = uniqAway (getTCvInScope subst) (setVarType old_var k1) + + -- old_var :: s1 ~r s2 + -- eta :: (s1' ~r s2') ~N (t1 ~r t2) + -- eta1 :: s1' ~r t1 + -- eta2 :: s2' ~r t2 + -- co1 :: s1' ~r s2' + -- co2 :: t1 ~r t2 + -- kind_co :: (s1' ~r s2') ~N (t1 ~r t2) + -- lifted :: co1 ~N co2 + + role = coVarRole old_var + eta' = downgradeRole role Nominal eta + eta1 = mkNthCo role 2 eta' + eta2 = mkNthCo role 3 eta' + + co1 = mkCoVarCo new_var + co2 = mkSymCo eta1 `mkTransCo` co1 `mkTransCo` eta2 + kind_co = mkTyConAppCo Nominal (equalityTyCon role) + [ mkKindCo co1, mkKindCo co2 + , co1 , co2 ] + lifted = mkProofIrrelCo Nominal kind_co co1 co2 + new_cenv = extendVarEnv cenv old_var lifted -- | Is a var in the domain of a lifting context? @@ -1733,23 +2043,28 @@ lcInScopeSet (LC subst _) = getTCvInScope subst %************************************************************************ -} +seqMCo :: MCoercion -> () +seqMCo MRefl = () +seqMCo (MCo co) = seqCo co + seqCo :: Coercion -> () -seqCo (Refl r ty) = r `seq` seqType ty +seqCo (Refl ty) = seqType ty +seqCo (GRefl r ty mco) = r `seq` seqType ty `seq` seqMCo mco seqCo (TyConAppCo r tc cos) = r `seq` tc `seq` seqCos cos seqCo (AppCo co1 co2) = seqCo co1 `seq` seqCo co2 -seqCo (ForAllCo tv k co) = seqType (tyVarKind tv) `seq` seqCo k - `seq` seqCo co +seqCo (ForAllCo tv k co) = seqType (varType tv) `seq` seqCo k + `seq` seqCo co seqCo (FunCo r co1 co2) = r `seq` seqCo co1 `seq` seqCo co2 seqCo (CoVarCo cv) = cv `seq` () +seqCo (HoleCo h) = coHoleCoVar h `seq` () seqCo (AxiomInstCo con ind cos) = con `seq` ind `seq` seqCos cos seqCo (UnivCo p r t1 t2) = seqProv p `seq` r `seq` seqType t1 `seq` seqType t2 seqCo (SymCo co) = seqCo co seqCo (TransCo co1 co2) = seqCo co1 `seq` seqCo co2 -seqCo (NthCo n co) = n `seq` seqCo co +seqCo (NthCo r n co) = r `seq` n `seq` seqCo co seqCo (LRCo lr co) = lr `seq` seqCo co seqCo (InstCo co arg) = seqCo co `seq` seqCo arg -seqCo (CoherenceCo co1 co2) = seqCo co1 `seq` seqCo co2 seqCo (KindCo co) = seqCo co seqCo (SubCo co) = seqCo co seqCo (AxiomRuleCo _ cs) = seqCos cs @@ -1759,7 +2074,6 @@ seqProv UnsafeCoerceProv = () seqProv (PhantomProv co) = seqCo co seqProv (ProofIrrelProv co) = seqCo co seqProv (PluginProv _) = () -seqProv (HoleProv _) = () seqCos :: [Coercion] -> () seqCos [] = () @@ -1771,19 +2085,6 @@ seqCos (co:cos) = seqCo co `seq` seqCos cos The kind of a type, and of a coercion %* * %************************************************************************ - -Note [Computing a coercion kind and role] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To compute a coercion's kind is straightforward: see coercionKind. -But to compute a coercion's role, in the case for NthCo we need -its kind as well. So if we have two separate functions (one for kinds -and one for roles) we can get exponentially bad behaviour, since each -NthCo node makes a separate call to coercionKind, which traverses the -sub-tree again. This was part of the problem in Trac #9233. - -Solution: compute both together; hence coercionKindRole. We keep a -separate coercionKind function because it's a bit more efficient if -the kind is all you want. -} coercionType :: Coercion -> Type @@ -1798,24 +2099,23 @@ coercionType co = case coercionKindRole co of -- i.e. the kind of @c@ relates @t1@ and @t2@, then @coercionKind c = Pair t1 t2@. coercionKind :: Coercion -> Pair Type -coercionKind co = go co +coercionKind co = + go co where - go (Refl _ ty) = Pair ty ty + go (Refl ty) = Pair ty ty + go (GRefl _ ty MRefl) = Pair ty ty + go (GRefl _ ty (MCo co1)) = Pair ty (mkCastTy ty co1) go (TyConAppCo _ tc cos)= mkTyConApp tc <$> (sequenceA $ map go cos) go (AppCo co1 co2) = mkAppTy <$> go co1 <*> go co2 - go (ForAllCo tv1 k_co co) - = let Pair _ k2 = go k_co - tv2 = setTyVarKind tv1 k2 - Pair ty1 ty2 = go co - subst = zipTvSubst [tv1] [TyVarTy tv2 `mk_cast_ty` mkSymCo k_co] - ty2' = substTyAddInScope subst ty2 in - -- We need free vars of ty2 in scope to satisfy the invariant - -- from Note [The substitution invariant] - -- This is doing repeated substitutions and probably doesn't - -- need to, see #11735 - mkInvForAllTy <$> Pair tv1 tv2 <*> Pair ty1 ty2' + go co@(ForAllCo tv1 k_co co1) -- works for both tyvar and covar + | isGReflCo k_co = mkTyCoInvForAllTy tv1 <$> go co1 + -- kind_co always has kind @Type@, thus @isGReflCo@ + | otherwise = go_forall empty_subst co + where + empty_subst = mkEmptyTCvSubst (mkInScopeSet $ tyCoVarsOfCo co) go (FunCo _ co1 co2) = mkFunTy <$> go co1 <*> go co2 go (CoVarCo cv) = coVarTypes cv + go (HoleCo h) = coVarTypes (coHoleCoVar h) go (AxiomInstCo ax ind cos) | CoAxBranch { cab_tvs = tvs, cab_cvs = cvs , cab_lhs = lhs, cab_rhs = rhs } <- coAxiomNthBranch ax ind @@ -1835,7 +2135,7 @@ coercionKind co = go co go (UnivCo _ _ ty1 ty2) = Pair ty1 ty2 go (SymCo co) = swap $ go co go (TransCo co1 co2) = Pair (pFst $ go co1) (pSnd $ go co2) - go g@(NthCo d co) + go g@(NthCo _ d co) | Just argss <- traverse tyConAppArgs_maybe tys = ASSERT( and $ (`lengthExceeds` d) <$> argss ) (`getNth` d) <$> argss @@ -1850,9 +2150,6 @@ coercionKind co = go co tys = go co go (LRCo lr co) = (pickLR lr . splitAppTy) <$> go co go (InstCo aco arg) = go_app aco [arg] - go (CoherenceCo g h) - = let Pair ty1 ty2 = go g in - Pair (mkCastTy ty1 h) ty2 go (KindCo co) = typeKind <$> go co go (SubCo co) = go co go (AxiomRuleCo ax cos) = expectJust "coercionKind" $ @@ -1864,84 +2161,92 @@ coercionKind co = go co go_app (InstCo co arg) args = go_app co (arg:args) go_app co args = piResultTys <$> go co <*> (sequenceA $ map go args) - -- The real mkCastTy is too slow, and we can easily have nested ForAllCos. - mk_cast_ty :: Type -> Coercion -> Type - mk_cast_ty ty (Refl {}) = ty - mk_cast_ty ty co = CastTy ty co + go_forall subst (ForAllCo tv1 k_co co) + -- See Note [Nested ForAllCos] + | isTyVar tv1 + = mkInvForAllTy <$> Pair tv1 tv2 <*> go_forall subst' co + where + Pair _ k2 = go k_co + tv2 = setTyVarKind tv1 (substTy subst k2) + subst' | isGReflCo k_co = extendTCvInScope subst tv1 + -- kind_co always has kind @Type@, thus @isGReflCo@ + | otherwise = extendTvSubst (extendTCvInScope subst tv2) tv1 $ + TyVarTy tv2 `mkCastTy` mkSymCo k_co + go_forall subst (ForAllCo cv1 k_co co) + | isCoVar cv1 + = mkTyCoInvForAllTy <$> Pair cv1 cv2 <*> go_forall subst' co + where + Pair _ k2 = go k_co + r = coVarRole cv1 + eta1 = mkNthCo r 2 (downgradeRole r Nominal k_co) + eta2 = mkNthCo r 3 (downgradeRole r Nominal k_co) + + -- k_co :: (t1 ~r t2) ~N (s1 ~r s2) + -- k1 = t1 ~r t2 + -- k2 = s1 ~r s2 + -- cv1 :: t1 ~r t2 + -- cv2 :: s1 ~r s2 + -- eta1 :: t1 ~r s1 + -- eta2 :: t2 ~r s2 + -- n_subst = (eta1 ; cv2 ; sym eta2) :: t1 ~r t2 + + cv2 = setVarType cv1 (substTy subst k2) + n_subst = eta1 `mkTransCo` (mkCoVarCo cv2) `mkTransCo` (mkSymCo eta2) + subst' | isReflCo k_co = extendTCvInScope subst cv1 + | otherwise = extendCvSubst (extendTCvInScope subst cv2) + cv1 n_subst + + go_forall subst other_co + -- when other_co is not a ForAllCo + = substTy subst `pLiftSnd` go other_co + +{- + +Note [Nested ForAllCos] +~~~~~~~~~~~~~~~~~~~~~~~ + +Suppose we need `coercionKind (ForAllCo a1 (ForAllCo a2 ... (ForAllCo an +co)...) )`. We do not want to perform `n` single-type-variable +substitutions over the kind of `co`; rather we want to do one substitution +which substitutes for all of `a1`, `a2` ... simultaneously. If we do one +at a time we get the performance hole reported in Trac #11735. + +Solution: gather up the type variables for nested `ForAllCos`, and +substitute for them all at once. Remarkably, for Trac #11735 this single +change reduces /total/ compile time by a factor of more than ten. + +-} -- | Apply 'coercionKind' to multiple 'Coercion's coercionKinds :: [Coercion] -> Pair [Type] coercionKinds tys = sequenceA $ map coercionKind tys -- | Get a coercion's kind and role. --- Why both at once? See Note [Computing a coercion kind and role] coercionKindRole :: Coercion -> (Pair Type, Role) -coercionKindRole = go - where - go (Refl r ty) = (Pair ty ty, r) - go (TyConAppCo r tc cos) - = (mkTyConApp tc <$> (sequenceA $ map coercionKind cos), r) - go (AppCo co1 co2) - = let (tys1, r1) = go co1 in - (mkAppTy <$> tys1 <*> coercionKind co2, r1) - go (ForAllCo tv1 k_co co) - = let Pair _ k2 = coercionKind k_co - tv2 = setTyVarKind tv1 k2 - (Pair ty1 ty2, r) = go co - subst = zipTvSubst [tv1] [TyVarTy tv2 `mkCastTy` mkSymCo k_co] - ty2' = substTyAddInScope subst ty2 in - -- We need free vars of ty2 in scope to satisfy the invariant - -- from Note [The substitution invariant] - -- This is doing repeated substitutions and probably doesn't - -- need to, see #11735 - (mkInvForAllTy <$> Pair tv1 tv2 <*> Pair ty1 ty2', r) - go (FunCo r co1 co2) - = (mkFunTy <$> coercionKind co1 <*> coercionKind co2, r) - go (CoVarCo cv) = (coVarTypes cv, coVarRole cv) - go co@(AxiomInstCo ax _ _) = (coercionKind co, coAxiomRole ax) - go (UnivCo _ r ty1 ty2) = (Pair ty1 ty2, r) - go (SymCo co) = first swap $ go co - go (TransCo co1 co2) - = let (tys1, r) = go co1 in - (Pair (pFst tys1) (pSnd $ coercionKind co2), r) - go (NthCo d co) - | Just (tv1, _) <- splitForAllTy_maybe ty1 - = ASSERT( d == 0 ) - let (tv2, _) = splitForAllTy ty2 in - (tyVarKind <$> Pair tv1 tv2, Nominal) - - | otherwise - = let (tc1, args1) = splitTyConApp ty1 - (_tc2, args2) = splitTyConApp ty2 - in - ASSERT2( tc1 == _tc2, ppr d $$ ppr tc1 $$ ppr _tc2 ) - ((`getNth` d) <$> Pair args1 args2, nthRole r tc1 d) - - where - (Pair ty1 ty2, r) = go co - go co@(LRCo {}) = (coercionKind co, Nominal) - go (InstCo co arg) = go_app co [arg] - go (CoherenceCo co1 co2) - = let (Pair t1 t2, r) = go co1 in - (Pair (t1 `mkCastTy` co2) t2, r) - go co@(KindCo {}) = (coercionKind co, Nominal) - go (SubCo co) = (coercionKind co, Representational) - go co@(AxiomRuleCo ax _) = (coercionKind co, coaxrRole ax) - - go_app :: Coercion -> [Coercion] -> (Pair Type, Role) - -- Collect up all the arguments and apply all at once - -- See Note [Nested InstCos] - go_app (InstCo co arg) args = go_app co (arg:args) - go_app co args - = let (pair, r) = go co in - (piResultTys <$> pair <*> (sequenceA $ map coercionKind args), r) +coercionKindRole co = (coercionKind co, coercionRole co) -- | Retrieve the role from a coercion. coercionRole :: Coercion -> Role -coercionRole = snd . coercionKindRole - -- There's not a better way to do this, because NthCo needs the *kind* - -- and role of its argument. Luckily, laziness should generally avoid - -- the need for computing kinds in other cases. +coercionRole = go + where + go (Refl _) = Nominal + go (GRefl r _ _) = r + go (TyConAppCo r _ _) = r + go (AppCo co1 _) = go co1 + go (ForAllCo _ _ co) = go co + go (FunCo r _ _) = r + go (CoVarCo cv) = coVarRole cv + go (HoleCo h) = coVarRole (coHoleCoVar h) + go (AxiomInstCo ax _ _) = coAxiomRole ax + go (UnivCo _ r _ _) = r + go (SymCo co) = go co + go (TransCo co1 _co2) = go co1 + go (NthCo r _d _co) = r + go (LRCo {}) = Nominal + go (InstCo co _) = go co + go (KindCo {}) = Nominal + go (SubCo _) = Representational + go (AxiomRuleCo ax _) = coaxrRole ax {- Note [Nested InstCos] @@ -1959,3 +2264,94 @@ So it's very important to do the substitution simultaneously; cf Type.piResultTys (which in fact we call here). -} + +-- | Assuming that two types are the same, ignoring coercions, find +-- a nominal coercion between the types. This is useful when optimizing +-- transitivity over coercion applications, where splitting two +-- AppCos might yield different kinds. See Note [EtaAppCo] in OptCoercion. +buildCoercion :: Type -> Type -> CoercionN +buildCoercion orig_ty1 orig_ty2 = go orig_ty1 orig_ty2 + where + go ty1 ty2 | Just ty1' <- coreView ty1 = go ty1' ty2 + | Just ty2' <- coreView ty2 = go ty1 ty2' + + go (CastTy ty1 co) ty2 + = let co' = go ty1 ty2 + r = coercionRole co' + in mkCoherenceLeftCo r ty1 co co' + + go ty1 (CastTy ty2 co) + = let co' = go ty1 ty2 + r = coercionRole co' + in mkCoherenceRightCo r ty2 co co' + + go ty1@(TyVarTy tv1) _tyvarty + = ASSERT( case _tyvarty of + { TyVarTy tv2 -> tv1 == tv2 + ; _ -> False } ) + mkNomReflCo ty1 + + go (FunTy arg1 res1) (FunTy arg2 res2) + = mkFunCo Nominal (go arg1 arg2) (go res1 res2) + + go (TyConApp tc1 args1) (TyConApp tc2 args2) + = ASSERT( tc1 == tc2 ) + mkTyConAppCo Nominal tc1 (zipWith go args1 args2) + + go (AppTy ty1a ty1b) ty2 + | Just (ty2a, ty2b) <- repSplitAppTy_maybe ty2 + = mkAppCo (go ty1a ty2a) (go ty1b ty2b) + + go ty1 (AppTy ty2a ty2b) + | Just (ty1a, ty1b) <- repSplitAppTy_maybe ty1 + = mkAppCo (go ty1a ty2a) (go ty1b ty2b) + + go (ForAllTy (Bndr tv1 _flag1) ty1) (ForAllTy (Bndr tv2 _flag2) ty2) + | isTyVar tv1 + = ASSERT( isTyVar tv2 ) + mkForAllCo tv1 kind_co (go ty1 ty2') + where kind_co = go (tyVarKind tv1) (tyVarKind tv2) + in_scope = mkInScopeSet $ tyCoVarsOfType ty2 `unionVarSet` tyCoVarsOfCo kind_co + ty2' = substTyWithInScope in_scope [tv2] + [mkTyVarTy tv1 `mkCastTy` kind_co] + ty2 + + go (ForAllTy (Bndr cv1 _flag1) ty1) (ForAllTy (Bndr cv2 _flag2) ty2) + = ASSERT( isCoVar cv1 && isCoVar cv2 ) + mkForAllCo cv1 kind_co (go ty1 ty2') + where s1 = varType cv1 + s2 = varType cv2 + kind_co = go s1 s2 + + -- s1 = t1 ~r t2 + -- s2 = t3 ~r t4 + -- kind_co :: (t1 ~r t2) ~N (t3 ~r t4) + -- eta1 :: t1 ~r t3 + -- eta2 :: t2 ~r t4 + + r = coVarRole cv1 + kind_co' = downgradeRole r Nominal kind_co + eta1 = mkNthCo r 2 kind_co' + eta2 = mkNthCo r 3 kind_co' + + subst = mkEmptyTCvSubst $ mkInScopeSet $ + tyCoVarsOfType ty2 `unionVarSet` tyCoVarsOfCo kind_co + ty2' = substTy (extendCvSubst subst cv2 $ mkSymCo eta1 `mkTransCo` + mkCoVarCo cv1 `mkTransCo` + eta2) + ty2 + + go ty1@(LitTy lit1) _lit2 + = ASSERT( case _lit2 of + { LitTy lit2 -> lit1 == lit2 + ; _ -> False } ) + mkNomReflCo ty1 + + go (CoercionTy co1) (CoercionTy co2) + = mkProofIrrelCo Nominal kind_co co1 co2 + where + kind_co = go (coercionType co1) (coercionType co2) + + go ty1 ty2 + = pprPanic "buildKindCoercion" (vcat [ ppr orig_ty1, ppr orig_ty2 + , ppr ty1, ppr ty2 ]) diff --git a/compiler/types/Coercion.hs-boot b/compiler/types/Coercion.hs-boot index dd10d6e5ca..89aab441de 100644 --- a/compiler/types/Coercion.hs-boot +++ b/compiler/types/Coercion.hs-boot @@ -2,13 +2,14 @@ module Coercion where +import GhcPrelude + import {-# SOURCE #-} TyCoRep import {-# SOURCE #-} TyCon import BasicTypes ( LeftOrRight ) import CoAxiom import Var -import Outputable import Pair import Util @@ -24,19 +25,21 @@ mkUnsafeCo :: Role -> Type -> Type -> Coercion mkUnivCo :: UnivCoProvenance -> Role -> Type -> Type -> Coercion mkSymCo :: Coercion -> Coercion mkTransCo :: Coercion -> Coercion -> Coercion -mkNthCo :: Int -> Coercion -> Coercion +mkNthCo :: HasDebugCallStack => Role -> Int -> Coercion -> Coercion mkLRCo :: LeftOrRight -> Coercion -> Coercion mkInstCo :: Coercion -> Coercion -> Coercion -mkCoherenceCo :: Coercion -> Coercion -> Coercion +mkGReflCo :: Role -> Type -> MCoercionN -> Coercion +mkNomReflCo :: Type -> Coercion mkKindCo :: Coercion -> Coercion mkSubCo :: Coercion -> Coercion mkProofIrrelCo :: Role -> Coercion -> Coercion -> Coercion -> Coercion +mkAxiomRuleCo :: CoAxiomRule -> [Coercion] -> Coercion -mkFunCos :: Role -> [Coercion] -> Coercion -> Coercion - +isGReflCo :: Coercion -> Bool isReflCo :: Coercion -> Bool isReflexiveCo :: Coercion -> Bool -coVarKindsTypesRole :: CoVar -> (Kind, Kind, Type, Type, Role) +decomposePiCos :: HasDebugCallStack => Coercion -> Pair Type -> [Type] -> ([Coercion], Coercion) +coVarKindsTypesRole :: HasDebugCallStack => CoVar -> (Kind, Kind, Type, Type, Role) coVarRole :: CoVar -> Role mkCoercionType :: Role -> Type -> Type -> Type @@ -47,5 +50,3 @@ seqCo :: Coercion -> () coercionKind :: Coercion -> Pair Type coercionType :: Coercion -> Type - -pprCo :: Coercion -> SDoc diff --git a/compiler/types/FamInstEnv.hs b/compiler/types/FamInstEnv.hs index 6d179a9a10..a5cfba1afb 100644 --- a/compiler/types/FamInstEnv.hs +++ b/compiler/types/FamInstEnv.hs @@ -2,7 +2,7 @@ -- -- FamInstEnv: Type checked family instance declarations -{-# LANGUAGE CPP, GADTs, ScopedTypeVariables #-} +{-# LANGUAGE CPP, GADTs, ScopedTypeVariables, BangPatterns #-} module FamInstEnv ( FamInst(..), FamFlavor(..), famInstAxiom, famInstTyCon, famInstRHS, @@ -29,9 +29,8 @@ module FamInstEnv ( -- Normalisation topNormaliseType, topNormaliseType_maybe, - normaliseType, normaliseTcApp, + normaliseType, normaliseTcApp, normaliseTcArgs, reduceTyFamApp_maybe, - pmTopNormaliseType_maybe, -- Flattening flattenTys @@ -39,11 +38,12 @@ module FamInstEnv ( #include "HsVersions.h" +import GhcPrelude + import Unify import Type import TyCoRep import TyCon -import DataCon (DataCon) import Coercion import CoAxiom import VarSet @@ -53,7 +53,7 @@ import PrelNames ( eqPrimTyConKey ) import UniqDFM import Outputable import Maybes -import TrieMap +import CoreMap import Unique import Util import Var @@ -62,7 +62,8 @@ import SrcLoc import FastString import MonadUtils import Control.Monad -import Data.List( mapAccumL, find ) +import Data.List( mapAccumL ) +import Data.Array( Array, assocs ) {- ************************************************************************ @@ -125,8 +126,50 @@ data FamFlavor = SynFamilyInst -- A synonym family | DataFamilyInst TyCon -- A data family, with its representation TyCon -{- Note [Eta reduction for data families] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +{- +Note [Arity of data families] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Data family instances might legitimately be over- or under-saturated. + +Under-saturation has two potential causes: + U1) Eta reduction. See Note [Eta reduction for data families]. + U2) When the user has specified a return kind instead of written out patterns. + Example: + + data family Sing (a :: k) + data instance Sing :: Bool -> Type + + The data family tycon Sing has an arity of 2, the k and the a. But + the data instance has only one pattern, Bool (standing in for k). + This instance is equivalent to `data instance Sing (a :: Bool)`, but + without the last pattern, we have an under-saturated data family instance. + On its own, this example is not compelling enough to add support for + under-saturation, but U1 makes this feature more compelling. + +Over-saturation is also possible: + O1) If the data family's return kind is a type variable (see also #12369), + an instance might legitimately have more arguments than the family. + Example: + + data family Fix :: (Type -> k) -> k + data instance Fix f = MkFix1 (f (Fix f)) + data instance Fix f x = MkFix2 (f (Fix f x) x) + + In the first instance here, the k in the data family kind is chosen to + be Type. In the second, it's (Type -> Type). + + However, we require that any over-saturation is eta-reducible. That is, + we require that any extra patterns be bare unrepeated type variables; + see Note [Eta reduction for data families]. Accordingly, the FamInst + is never over-saturated. + +Why can we allow such flexibility for data families but not for type families? +Because data families can be decomposed -- that is, they are generative and +injective. A Type family is neither and so always must be applied to all its +arguments. + +Note [Eta reduction for data families] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider this data family T a b :: * newtype instance T Int a = MkT (IO a) deriving( Monad ) @@ -148,22 +191,31 @@ Solution: eta-reduce both axioms, thus: Now d' = d |> Monad (sym (ax2 ; ax1)) -This eta reduction happens for data instances as well as newtype -instances. Here we want to eta-reduce the data family axiom. -All this is done in TcInstDcls.tcDataFamInstDecl. +----- Bottom line ------ + +For a FamInst with fi_flavour = DataFamilyInst rep_tc, -See also Note [Newtype eta] in TyCon. + - fi_tvs (and cab_tvs of its CoAxiom) may be shorter + than tyConTyVars of rep_tc. -Bottom line: - For a FamInst with fi_flavour = DataFamilyInst rep_tc, - - fi_tvs may be shorter than tyConTyVars of rep_tc - fi_tys may be shorter than tyConArity of the family tycon i.e. LHS is unsaturated + - fi_rhs will be (rep_tc fi_tvs) i.e. RHS is un-saturated - But when fi_flavour = SynFamilyInst, + - This eta reduction happens for data instances as well + as newtype instances. Here we want to eta-reduce the data family axiom. + + - This eta-reduction is done in TcInstDcls.tcDataFamInstDecl. + +But when fi_flavour = SynFamilyInst, - fi_tys has the exact arity of the family tycon + + +(See also Note [Newtype eta] in TyCon. This is notionally separate +and deals with the axiom connecting a newtype with its representation +type; but it too is eta-reduced.) -} -- Obtain the axiom of a family instance @@ -219,7 +271,7 @@ instance Outputable FamInst where -- See pprTyThing.pprFamInst for printing for the user pprFamInst :: FamInst -> SDoc pprFamInst famInst - = hang (pprFamInstHdr famInst) 2 (ifPprDebug debug_stuff) + = hang (pprFamInstHdr famInst) 2 (whenPprDebug debug_stuff) where ax = fi_axiom famInst debug_stuff = vcat [ text "Coercion axiom:" <+> ppr ax @@ -415,7 +467,7 @@ familyInstances (pkg_fie, home_fie) fam Nothing -> [] extendFamInstEnvList :: FamInstEnv -> [FamInst] -> FamInstEnv -extendFamInstEnvList inst_env fis = foldl extendFamInstEnv inst_env fis +extendFamInstEnvList inst_env fis = foldl' extendFamInstEnv inst_env fis extendFamInstEnv :: FamInstEnv -> FamInst -> FamInstEnv extendFamInstEnv inst_env @@ -469,7 +521,7 @@ go back to all previous equations and check that, under the substitution induced by the match, other branches are surely apart. (See Note [Apartness].) This is similar to what happens with class instance selection, when we need to guarantee that there is only a match and -no unifiers. The exact algorithm is different here because the the +no unifiers. The exact algorithm is different here because the potentially-overlapping group is closed. As another example, consider this: @@ -603,8 +655,8 @@ mkCoAxBranch tvs cvs lhs rhs roles loc , cab_loc = loc , cab_incomps = placeHolderIncomps } where - (env1, tvs1) = tidyTyCoVarBndrs emptyTidyEnv tvs - (env, cvs1) = tidyTyCoVarBndrs env1 cvs + (env1, tvs1) = tidyVarBndrs emptyTidyEnv tvs + (env, cvs1) = tidyVarBndrs env1 cvs -- See Note [Tidy axioms when we build them] -- all of the following code is here to avoid mutual dependencies with @@ -932,7 +984,6 @@ lookup_fam_inst_env' match_fun ie fam match_tys -- No match => try next | otherwise = find rest - where (rough_tcs, match_tys1, match_tys2) = split_tys tpl_tys @@ -1079,21 +1130,25 @@ chooseBranch axiom tys (target_tys, extra_tys) = splitAt num_pats tys branches = coAxiomBranches axiom ; (ind, inst_tys, inst_cos) - <- findBranch (fromBranches branches) target_tys + <- findBranch (unMkBranches branches) target_tys ; return ( ind, inst_tys `chkAppend` extra_tys, inst_cos ) } -- The axiom must *not* be oversaturated -findBranch :: [CoAxBranch] -- branches to check - -> [Type] -- target types +findBranch :: Array BranchIndex CoAxBranch + -> [Type] -> Maybe (BranchIndex, [Type], [Coercion]) -- coercions relate requested types to returned axiom LHS at role N findBranch branches target_tys - = go 0 branches + = foldr go Nothing (assocs branches) where - go ind (branch@(CoAxBranch { cab_tvs = tpl_tvs, cab_cvs = tpl_cvs - , cab_lhs = tpl_lhs - , cab_incomps = incomps }) : rest) - = let in_scope = mkInScopeSet (unionVarSets $ + go :: (BranchIndex, CoAxBranch) + -> Maybe (BranchIndex, [Type], [Coercion]) + -> Maybe (BranchIndex, [Type], [Coercion]) + go (index, branch) other + = let (CoAxBranch { cab_tvs = tpl_tvs, cab_cvs = tpl_cvs + , cab_lhs = tpl_lhs + , cab_incomps = incomps }) = branch + in_scope = mkInScopeSet (unionVarSets $ map (tyCoVarsOfTypes . coAxBranchLHS) incomps) -- See Note [Flattening] below flattened_target = flattenTys in_scope target_tys @@ -1103,13 +1158,10 @@ findBranch branches target_tys -> -- matching worked & we're apart from all incompatible branches. -- success ASSERT( all (isJust . lookupCoVar subst) tpl_cvs ) - Just (ind, substTyVars subst tpl_tvs, substCoVars subst tpl_cvs) + Just (index, substTyVars subst tpl_tvs, substCoVars subst tpl_cvs) -- failure. keep looking - _ -> go (ind+1) rest - - -- fail if no branches left - go _ [] = Nothing + _ -> other -- | Do an apartness check, as described in the "Closed Type Families" paper -- (POPL '14). This should be used when determining if an equation @@ -1162,7 +1214,7 @@ Type) pairs. We also benefit because we can piggyback on the liftCoSubstVarBndr function to deal with binders. However, I had to modify that function to work with this -application. Thus, we now have liftCoSubstVarBndrCallback, which takes +application. Thus, we now have liftCoSubstVarBndrUsing, which takes a function used to process the kind of the binder. We don't wish to lift the kind, but instead normalise it. So, we pass in a callback function that processes the kind of the binder. @@ -1221,125 +1273,11 @@ topNormaliseType_maybe env ty tyFamStepper rec_nts tc tys -- Try to step a type/data family = let (args_co, ntys) = normaliseTcArgs env Representational tc tys in - -- NB: It's OK to use normaliseTcArgs here instead of - -- normalise_tc_args (which takes the LiftingContext described - -- in Note [Normalising types]) because the reduceTyFamApp below - -- works only at top level. We'll never recur in this function - -- after reducing the kind of a bound tyvar. - case reduceTyFamApp_maybe env Representational tc ntys of Just (co, rhs) -> NS_Step rec_nts rhs (args_co `mkTransCo` co) _ -> NS_Done --------------- -pmTopNormaliseType_maybe :: FamInstEnvs -> Type -> Maybe (Type, [DataCon], Type) --- ^ Get rid of *outermost* (or toplevel) --- * type function redex --- * data family redex --- * newtypes --- --- Behaves exactly like `topNormaliseType_maybe`, but instead of returning a --- coercion, it returns useful information for issuing pattern matching --- warnings. See Note [Type normalisation for EmptyCase] for details. -pmTopNormaliseType_maybe env typ - = do ((ty_f,tm_f), ty) <- topNormaliseTypeX stepper comb typ - return (eq_src_ty ty (typ : ty_f [ty]), tm_f [], ty) - where - -- Find the first type in the sequence of rewrites that is a data type, - -- newtype, or a data family application (not the representation tycon!). - -- This is the one that is equal (in source Haskell) to the initial type. - -- If none is found in the list, then all of them are type family - -- applications, so we simply return the last one, which is the *simplest*. - eq_src_ty :: Type -> [Type] -> Type - eq_src_ty ty tys = maybe ty id (find is_alg_or_data_family tys) - - is_alg_or_data_family :: Type -> Bool - is_alg_or_data_family ty = isClosedAlgType ty || isDataFamilyAppType ty - - -- For efficiency, represent both lists as difference lists. - -- comb performs the concatenation, for both lists. - comb (tyf1, tmf1) (tyf2, tmf2) = (tyf1 . tyf2, tmf1 . tmf2) - - stepper = newTypeStepper `composeSteppers` tyFamStepper - - -- A 'NormaliseStepper' that unwraps newtypes, careful not to fall into - -- a loop. If it would fall into a loop, it produces 'NS_Abort'. - newTypeStepper :: NormaliseStepper ([Type] -> [Type],[DataCon] -> [DataCon]) - newTypeStepper rec_nts tc tys - | Just (ty', _co) <- instNewTyCon_maybe tc tys - = case checkRecTc rec_nts tc of - Just rec_nts' -> let tyf = ((TyConApp tc tys):) - tmf = ((tyConSingleDataCon tc):) - in NS_Step rec_nts' ty' (tyf, tmf) - Nothing -> NS_Abort - | otherwise - = NS_Done - - tyFamStepper :: NormaliseStepper ([Type] -> [Type], [DataCon] -> [DataCon]) - tyFamStepper rec_nts tc tys -- Try to step a type/data family - = let (_args_co, ntys) = normaliseTcArgs env Representational tc tys in - -- NB: It's OK to use normaliseTcArgs here instead of - -- normalise_tc_args (which takes the LiftingContext described - -- in Note [Normalising types]) because the reduceTyFamApp below - -- works only at top level. We'll never recur in this function - -- after reducing the kind of a bound tyvar. - - case reduceTyFamApp_maybe env Representational tc ntys of - Just (_co, rhs) -> NS_Step rec_nts rhs ((rhs:), id) - _ -> NS_Done - -{- Note [Type normalisation for EmptyCase] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -EmptyCase is an exception for pattern matching, since it is strict. This means -that it boils down to checking whether the type of the scrutinee is inhabited. -Function pmTopNormaliseType_maybe gets rid of the outermost type function/data -family redex and newtypes, in search of an algebraic type constructor, which is -easier to check for inhabitation. - -It returns 3 results instead of one, because there are 2 subtle points: -1. Newtypes are isomorphic to the underlying type in core but not in the source - language, -2. The representational data family tycon is used internally but should not be - shown to the user - -Hence, if pmTopNormaliseType_maybe env ty = Just (src_ty, dcs, core_ty), then - (a) src_ty is the rewritten type which we can show to the user. That is, the - type we get if we rewrite type families but not data families or - newtypes. - (b) dcs is the list of data constructors "skipped", every time we normalise a - newtype to it's core representation, we keep track of the source data - constructor. - (c) core_ty is the rewritten type. That is, - pmTopNormaliseType_maybe env ty = Just (src_ty, dcs, core_ty) - implies - topNormaliseType_maybe env ty = Just (co, core_ty) - for some coercion co. - -To see how all cases come into play, consider the following example: - - data family T a :: * - data instance T Int = T1 | T2 Bool - -- Which gives rise to FC: - -- data T a - -- data R:TInt = T1 | T2 Bool - -- axiom ax_ti : T Int ~R R:TInt - - newtype G1 = MkG1 (T Int) - newtype G2 = MkG2 G1 - - type instance F Int = F Char - type instance F Char = G2 - -In this case pmTopNormaliseType_maybe env (F Int) results in - - Just (G2, [MkG2,MkG1], R:TInt) - -Which means that in source Haskell: - - G2 is equivalent to F Int (in contrast, G1 isn't). - - if (x : R:TInt) then (MkG2 (MkG1 x) : F Int). --} - ---------------- normaliseTcApp :: FamInstEnvs -> Role -> TyCon -> [Type] -> (Coercion, Type) -- See comments on normaliseType for the arguments of this function normaliseTcApp env role tc tys @@ -1356,13 +1294,7 @@ normalise_tc_app tc tys -- See Note [Normalisation and type synonyms] normalise_type (mkAppTys (substTy (mkTvSubstPrs tenv) rhs) tys') - | not (isTypeFamilyTyCon tc) - = -- A synonym with no type families in the RHS; or data type etc - -- Just normalise the arguments and rebuild - do { (args_co, ntys) <- normalise_tc_args tc tys - ; return (args_co, mkTyConApp tc ntys) } - - | otherwise + | isFamilyTyCon tc = -- A type-family application do { env <- getEnv ; role <- getRole @@ -1376,6 +1308,12 @@ normalise_tc_app tc tys -- we do not do anything return (args_co, mkTyConApp tc ntys) } + | otherwise + = -- A synonym with no type families in the RHS; or data type etc + -- Just normalise the arguments and rebuild + do { (args_co, ntys) <- normalise_tc_args tc tys + ; return (args_co, mkTyConApp tc ntys) } + --------------- -- | Normalise arguments to a tycon normaliseTcArgs :: FamInstEnvs -- ^ env't with family instances @@ -1406,15 +1344,15 @@ normaliseType env role ty = initNormM env role (tyCoVarsOfType ty) $ normalise_type ty normalise_type :: Type -- old type - -> NormM (Coercion, Type) -- (coercion,new type), where - -- co :: old-type ~ new_type + -> NormM (Coercion, Type) -- (coercion, new type), where + -- co :: old-type ~ new_type -- Normalise the input type, by eliminating *all* type-function redexes -- but *not* newtypes (which are visible to the programmer) -- Returns with Refl if nothing happens -- Does nothing to newtypes -- The returned coercion *must* be *homogeneous* -- See Note [Normalising types] --- Try to not to disturb type synonyms if possible +-- Try not to disturb type synonyms if possible normalise_type ty = go ty @@ -1431,17 +1369,18 @@ normalise_type ty ; (co2, nty2) <- go ty2 ; r <- getRole ; return (mkFunCo r co1 co2, mkFunTy nty1 nty2) } - go (ForAllTy (TvBndr tyvar vis) ty) - = do { (lc', tv', h, ki') <- normalise_tyvar_bndr tyvar + go (ForAllTy (Bndr tcvar vis) ty) + = do { (lc', tv', h, ki') <- normalise_var_bndr tcvar ; (co, nty) <- withLC lc' $ normalise_type ty ; let tv2 = setTyVarKind tv' ki' - ; return (mkForAllCo tv' h co, ForAllTy (TvBndr tv2 vis) nty) } + ; return (mkForAllCo tv' h co, ForAllTy (Bndr tv2 vis) nty) } go (TyVarTy tv) = normalise_tyvar tv go (CastTy ty co) = do { (nco, nty) <- go ty ; lc <- getLC ; let co' = substRightCo lc co - ; return (castCoercionKind nco co co', mkCastTy nty co') } + ; return (castCoercionKind nco Nominal ty nty co co' + , mkCastTy nty co') } go (CoercionTy co) = do { lc <- getLC ; r <- getRole @@ -1461,12 +1400,13 @@ normalise_tyvar tv Nothing -> (mkReflCo r ty, ty) } where ty = mkTyVarTy tv -normalise_tyvar_bndr :: TyVar -> NormM (LiftingContext, TyVar, Coercion, Kind) -normalise_tyvar_bndr tv +normalise_var_bndr :: TyCoVar -> NormM (LiftingContext, TyCoVar, Coercion, Kind) +normalise_var_bndr tcvar + -- works for both tvar and covar = do { lc1 <- getLC ; env <- getEnv ; let callback lc ki = runNormM (normalise_type ki) env lc Nominal - ; return $ liftCoSubstVarBndrCallback callback lc1 tv } + ; return $ liftCoSubstVarBndrUsing callback lc1 tcvar } -- | a monad for the normalisation functions, reading 'FamInstEnvs', -- a 'LiftingContext', and a 'Role'. @@ -1565,7 +1505,7 @@ flattenTys in_scope tys = snd $ coreFlattenTys env tys -- *anywhere* in the types we're flattening, even if locally-bound in -- a forall. That way, we can ensure consistency both within and outside -- of that forall. - all_in_scope = in_scope `extendInScopeSetSet` allTyVarsInTys tys + all_in_scope = in_scope `extendInScopeSetSet` allTyCoVarsInTys tys env = emptyFlattenEnv all_in_scope coreFlattenTys :: FlattenEnv -> [Type] -> (FlattenEnv, [Type]) @@ -1600,10 +1540,10 @@ coreFlattenTy = go (env2, ty2') = go env1 ty2 in (env2, mkFunTy ty1' ty2') - go env (ForAllTy (TvBndr tv vis) ty) + go env (ForAllTy (Bndr tv vis) ty) = let (env1, tv') = coreFlattenVarBndr env tv (env2, ty') = go env1 ty in - (env2, ForAllTy (TvBndr tv' vis) ty') + (env2, ForAllTy (Bndr tv' vis) ty') go env ty@(LitTy {}) = (env, ty) @@ -1627,20 +1567,20 @@ coreFlattenCo env co covar = uniqAway in_scope (mkCoVar fresh_name kind') env2 = env1 { fe_subst = subst1 `extendTCvInScope` covar } -coreFlattenVarBndr :: FlattenEnv -> TyVar -> (FlattenEnv, TyVar) +coreFlattenVarBndr :: FlattenEnv -> TyCoVar -> (FlattenEnv, TyCoVar) coreFlattenVarBndr env tv | kind' `eqType` kind - = ( env { fe_subst = extendTvSubst old_subst tv (mkTyVarTy tv) } + = ( env { fe_subst = extendTCvSubst old_subst tv (mkTyCoVarTy tv) } -- override any previous binding for tv , tv) | otherwise - = let new_tv = uniqAway (getTCvInScope old_subst) (setTyVarKind tv kind') - new_subst = extendTvSubstWithClone old_subst tv new_tv + = let new_tv = uniqAway (getTCvInScope old_subst) (setVarType tv kind') + new_subst = extendTCvSubstWithClone old_subst tv new_tv in (env' { fe_subst = new_subst }, new_tv) where - kind = tyVarKind tv + kind = varType tv (env', kind') = coreFlattenTy env kind old_subst = fe_subst env @@ -1666,43 +1606,47 @@ coreFlattenTyFamApp env fam_tc fam_args FlattenEnv { fe_type_map = type_map , fe_subst = subst } = env --- | Get the set of all type variables mentioned anywhere in the list +-- | Get the set of all type/coercion variables mentioned anywhere in the list -- of types. These variables are not necessarily free. -allTyVarsInTys :: [Type] -> VarSet -allTyVarsInTys [] = emptyVarSet -allTyVarsInTys (ty:tys) = allTyVarsInTy ty `unionVarSet` allTyVarsInTys tys +allTyCoVarsInTys :: [Type] -> VarSet +allTyCoVarsInTys [] = emptyVarSet +allTyCoVarsInTys (ty:tys) = allTyCoVarsInTy ty `unionVarSet` allTyCoVarsInTys tys --- | Get the set of all type variables mentioned anywhere in a type. -allTyVarsInTy :: Type -> VarSet -allTyVarsInTy = go +-- | Get the set of all type/coercion variables mentioned anywhere in a type. +allTyCoVarsInTy :: Type -> VarSet +allTyCoVarsInTy = go where go (TyVarTy tv) = unitVarSet tv - go (TyConApp _ tys) = allTyVarsInTys tys + go (TyConApp _ tys) = allTyCoVarsInTys tys go (AppTy ty1 ty2) = (go ty1) `unionVarSet` (go ty2) go (FunTy ty1 ty2) = (go ty1) `unionVarSet` (go ty2) - go (ForAllTy (TvBndr tv _) ty) = unitVarSet tv `unionVarSet` - go (tyVarKind tv) `unionVarSet` - go ty - -- Don't remove the tv from the set! + go (ForAllTy (Bndr tv _) ty) = unitVarSet tv `unionVarSet` + go (tyVarKind tv) `unionVarSet` + go ty + -- Don't remove the tv from the set! go (LitTy {}) = emptyVarSet go (CastTy ty co) = go ty `unionVarSet` go_co co go (CoercionTy co) = go_co co - go_co (Refl _ ty) = go ty + go_mco MRefl = emptyVarSet + go_mco (MCo co) = go_co co + + go_co (Refl ty) = go ty + go_co (GRefl _ ty mco) = go ty `unionVarSet` go_mco mco go_co (TyConAppCo _ _ args) = go_cos args go_co (AppCo co arg) = go_co co `unionVarSet` go_co arg go_co (ForAllCo tv h co) = unionVarSets [unitVarSet tv, go_co co, go_co h] go_co (FunCo _ c1 c2) = go_co c1 `unionVarSet` go_co c2 go_co (CoVarCo cv) = unitVarSet cv + go_co (HoleCo h) = unitVarSet (coHoleCoVar h) go_co (AxiomInstCo _ _ cos) = go_cos cos go_co (UnivCo p _ t1 t2) = go_prov p `unionVarSet` go t1 `unionVarSet` go t2 go_co (SymCo co) = go_co co go_co (TransCo c1 c2) = go_co c1 `unionVarSet` go_co c2 - go_co (NthCo _ co) = go_co co + go_co (NthCo _ _ co) = go_co co go_co (LRCo _ co) = go_co co go_co (InstCo co arg) = go_co co `unionVarSet` go_co arg - go_co (CoherenceCo c1 c2) = go_co c1 `unionVarSet` go_co c2 go_co (KindCo co) = go_co co go_co (SubCo co) = go_co co go_co (AxiomRuleCo _ cs) = go_cos cs @@ -1713,7 +1657,6 @@ allTyVarsInTy = go go_prov (PhantomProv co) = go_co co go_prov (ProofIrrelProv co) = go_co co go_prov (PluginProv _) = emptyVarSet - go_prov (HoleProv _) = emptyVarSet mkFlattenFreshTyName :: Uniquable a => a -> Name mkFlattenFreshTyName unq diff --git a/compiler/types/InstEnv.hs b/compiler/types/InstEnv.hs index 8198a5360f..c45aa7cccd 100644 --- a/compiler/types/InstEnv.hs +++ b/compiler/types/InstEnv.hs @@ -18,9 +18,12 @@ module InstEnv ( fuzzyClsInstCmp, orphNamesOfClsInst, InstEnvs(..), VisibleOrphanModules, InstEnv, - emptyInstEnv, extendInstEnv, deleteFromInstEnv, identicalClsInstHead, + emptyInstEnv, extendInstEnv, + deleteFromInstEnv, deleteDFunFromInstEnv, + identicalClsInstHead, extendInstEnvList, lookupUniqueInstEnv, lookupInstEnv, instEnvElts, - memberInstEnv, instIsVisible, + memberInstEnv, + instIsVisible, classInstances, instanceBindFun, instanceCantMatch, roughMatchTcs, isOverlappable, isOverlapping, isIncoherent @@ -28,6 +31,8 @@ module InstEnv ( #include "HsVersions.h" +import GhcPrelude + import TcType -- InstEnv is really part of the type checker, -- and depends on TcType in many ways import CoreSyn ( IsOrphan(..), isOrphan, chooseOrphanAnchor ) @@ -213,7 +218,7 @@ pprInstance :: ClsInst -> SDoc pprInstance ispec = hang (pprInstanceHdr ispec) 2 (vcat [ text "--" <+> pprDefinedAt (getName ispec) - , ifPprDebug (ppr (is_dfun ispec)) ]) + , whenPprDebug (ppr (is_dfun ispec)) ]) -- * pprInstanceHdr is used in VStudio to populate the ClassView tree pprInstanceHdr :: ClsInst -> SDoc @@ -430,11 +435,11 @@ instIsVisible vis_mods ispec -- NB: Instances from the interactive package always are visible. We can't -- add interactive modules to the set since we keep creating new ones -- as a GHCi session progresses. - | isInteractiveModule mod = True - | IsOrphan <- is_orphan ispec = mod `elemModuleSet` vis_mods - | otherwise = True - where - mod = nameModule $ is_dfun_name ispec + = case nameModule_maybe (is_dfun_name ispec) of + Nothing -> True + Just mod | isInteractiveModule mod -> True + | IsOrphan <- is_orphan ispec -> mod `elemModuleSet` vis_mods + | otherwise -> True classInstances :: InstEnvs -> Class -> [ClsInst] classInstances (InstEnvs { ie_global = pkg_ie, ie_local = home_ie, ie_visible = vis_mods }) cls @@ -455,7 +460,7 @@ memberInstEnv inst_env ins_item@(ClsInst { is_cls_nm = cls_nm } ) = eqType (varType (is_dfun cls1)) (varType (is_dfun cls2)) extendInstEnvList :: InstEnv -> [ClsInst] -> InstEnv -extendInstEnvList inst_env ispecs = foldl extendInstEnv inst_env ispecs +extendInstEnvList inst_env ispecs = foldl' extendInstEnv inst_env ispecs extendInstEnv :: InstEnv -> ClsInst -> InstEnv extendInstEnv inst_env ins_item@(ClsInst { is_cls_nm = cls_nm }) @@ -469,6 +474,15 @@ deleteFromInstEnv inst_env ins_item@(ClsInst { is_cls_nm = cls_nm }) where adjust (ClsIE items) = ClsIE (filterOut (identicalClsInstHead ins_item) items) +deleteDFunFromInstEnv :: InstEnv -> DFunId -> InstEnv +-- Delete a specific instance fron an InstEnv +deleteDFunFromInstEnv inst_env dfun + = adjustUDFM adjust inst_env cls + where + (_, _, cls, _) = tcSplitDFunTy (idType dfun) + adjust (ClsIE items) = ClsIE (filterOut same_dfun items) + same_dfun (ClsInst { is_dfun = dfun' }) = dfun == dfun' + identicalClsInstHead :: ClsInst -> ClsInst -> Bool -- ^ True when when the instance heads are the same -- e.g. both are Eq [(a,b)] @@ -547,23 +561,38 @@ instance declaration itself, controlled as follows: Now suppose that, in some client module, we are searching for an instance of the target constraint (C ty1 .. tyn). The search works like this. - * Find all instances I that match the target constraint; that is, the - target constraint is a substitution instance of I. These instance - declarations are the candidates. +* Find all instances `I` that *match* the target constraint; that is, the + target constraint is a substitution instance of `I`. These instance + declarations are the *candidates*. - * Find all non-candidate instances that unify with the target - constraint. Such non-candidates instances might match when the - target constraint is further instantiated. If all of them are - incoherent, proceed; if not, the search fails. +* Eliminate any candidate `IX` for which both of the following hold: - * Eliminate any candidate IX for which both of the following hold: - * There is another candidate IY that is strictly more specific; - that is, IY is a substitution instance of IX but not vice versa. + - There is another candidate `IY` that is strictly more specific; that + is, `IY` is a substitution instance of `IX` but not vice versa. - * Either IX is overlappable or IY is overlapping. + - Either `IX` is *overlappable*, or `IY` is *overlapping*. (This + "either/or" design, rather than a "both/and" design, allow a + client to deliberately override an instance from a library, + without requiring a change to the library.) - * If only one candidate remains, pick it. Otherwise if all remaining - candidates are incoherent, pick an arbitrary candidate. Otherwise fail. +- If exactly one non-incoherent candidate remains, select it. If all + remaining candidates are incoherent, select an arbitrary one. + Otherwise the search fails (i.e. when more than one surviving + candidate is not incoherent). + +- If the selected candidate (from the previous step) is incoherent, the + search succeeds, returning that candidate. + +- If not, find all instances that *unify* with the target constraint, + but do not *match* it. Such non-candidate instances might match when + the target constraint is further instantiated. If all of them are + incoherent, the search succeeds, returning the selected candidate; if + not, the search fails. + +Notice that these rules are not influenced by flag settings in the +client module, where the instances are *used*. These rules make it +possible for a library author to design a library that relies on +overlapping instances without the client having to know. Note [Overlapping instances] (NB: these notes are quite old) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -674,7 +703,7 @@ prematurely chosing a generic instance when a more specific one exists. --Jeff -v + BUT NOTE [Nov 2001]: we must actually *unify* not reverse-match in this test. Suppose the instance envt had ..., forall a b. C a a b, ..., forall a b c. C a b c, ... @@ -739,7 +768,8 @@ lookupInstEnv' :: InstEnv -- InstEnv to look in -> VisibleOrphanModules -- But filter against this -> Class -> [Type] -- What we are looking for -> ([InstMatch], -- Successful matches - [ClsInst]) -- These don't match but do unify + [ClsInst]) -- These don't match but do unify + -- (no incoherent ones in here) -- The second component of the result pair happens when we look up -- Foo [a] -- in an InstEnv that has entries for @@ -776,7 +806,8 @@ lookupInstEnv' ie vis_mods cls tys = find ((item, map (lookupTyVar subst) tpl_tvs) : ms) us rest -- Does not match, so next check whether the things unify - -- See Note [Overlapping instances] and Note [Incoherent instances] + -- See Note [Overlapping instances] + -- Ignore ones that are incoherent: Note [Incoherent instances] | isIncoherent item = find ms us rest diff --git a/compiler/types/Kind.hs b/compiler/types/Kind.hs index ae11c8a651..f88bbe1c0d 100644 --- a/compiler/types/Kind.hs +++ b/compiler/types/Kind.hs @@ -3,24 +3,22 @@ {-# LANGUAGE CPP #-} module Kind ( -- * Main data type - Kind, typeKind, + Kind, -- ** Predicates on Kinds isLiftedTypeKind, isUnliftedTypeKind, - isConstraintKind, isTYPEApp, - returnsTyCon, returnsConstraintKind, isConstraintKindCon, classifiesTypeWithValues, - isStarKind, isStarKindSynonymTyCon, - tcIsStarKind, isKindLevPoly ) where #include "HsVersions.h" -import {-# SOURCE #-} Type ( typeKind, coreView, tcView +import GhcPrelude + +import {-# SOURCE #-} Type ( coreView , splitTyConApp_maybe ) import {-# SOURCE #-} DataCon ( DataCon ) @@ -38,7 +36,7 @@ import Util * * ************************************************************************ -Note [Kind Constraint and kind *] +Note [Kind Constraint and kind Type] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The kind Constraint is the kind of classes and other type constraints. The special thing about types of kind Constraint is that @@ -49,27 +47,22 @@ The special thing about types of kind Constraint is that to f. However, once type inference is over, there is *no* distinction between -Constraint and *. Indeed we can have coercions between the two. Consider +Constraint and Type. Indeed we can have coercions between the two. Consider class C a where op :: a -> a For this single-method class we may generate a newtype, which in turn generates an axiom witnessing C a ~ (a -> a) -so on the left we have Constraint, and on the right we have *. +so on the left we have Constraint, and on the right we have Type. See Trac #7451. -Bottom line: although '*' and 'Constraint' are distinct TyCons, with +Bottom line: although 'Type' and 'Constraint' are distinct TyCons, with distinct uniques, they are treated as equal at all times except during type inference. -} -isConstraintKind :: Kind -> Bool isConstraintKindCon :: TyCon -> Bool - -isConstraintKindCon tc = tyConUnique tc == constraintKindTyConKey - -isConstraintKind (TyConApp tc _) = isConstraintKindCon tc -isConstraintKind _ = False +isConstraintKindCon tc = tyConUnique tc == constraintKindTyConKey isTYPEApp :: Kind -> Maybe DataCon isTYPEApp (TyConApp tc args) @@ -80,22 +73,13 @@ isTYPEApp (TyConApp tc args) = Just dc isTYPEApp _ = Nothing --- | Does the given type "end" in the given tycon? For example @k -> [a] -> *@ --- ends in @*@ and @Maybe a -> [a]@ ends in @[]@. -returnsTyCon :: Unique -> Type -> Bool -returnsTyCon tc_u (ForAllTy _ ty) = returnsTyCon tc_u ty -returnsTyCon tc_u (FunTy _ ty) = returnsTyCon tc_u ty -returnsTyCon tc_u (TyConApp tc' _) = tc' `hasKey` tc_u -returnsTyCon _ _ = False - -returnsConstraintKind :: Kind -> Bool -returnsConstraintKind = returnsTyCon constraintKindTyConKey - -- | Tests whether the given kind (which should look like @TYPE x@) -- is something other than a constructor tree (that is, constructors at every node). +-- E.g. True of TYPE k, TYPE (F Int) +-- False of TYPE 'LiftedRep isKindLevPoly :: Kind -> Bool -isKindLevPoly k = ASSERT2( isStarKind k || _is_type, ppr k ) - -- the isStarKind check is necessary b/c of Constraint +isKindLevPoly k = ASSERT2( isLiftedTypeKind k || _is_type, ppr k ) + -- the isLiftedTypeKind check is necessary b/c of Constraint go k where go ty | Just ty' <- coreView ty = go ty' @@ -126,27 +110,4 @@ isKindLevPoly k = ASSERT2( isStarKind k || _is_type, ppr k ) -- like *, #, TYPE Lifted, TYPE v, Constraint. classifiesTypeWithValues :: Kind -> Bool -- ^ True of any sub-kind of OpenTypeKind -classifiesTypeWithValues t | Just t' <- coreView t = classifiesTypeWithValues t' -classifiesTypeWithValues (TyConApp tc [_]) = tc `hasKey` tYPETyConKey -classifiesTypeWithValues _ = False - --- | Is this kind equivalent to *? -tcIsStarKind :: Kind -> Bool -tcIsStarKind k | Just k' <- tcView k = isStarKind k' -tcIsStarKind (TyConApp tc [TyConApp ptr_rep []]) - = tc `hasKey` tYPETyConKey - && ptr_rep `hasKey` liftedRepDataConKey -tcIsStarKind _ = False - --- | Is this kind equivalent to *? -isStarKind :: Kind -> Bool -isStarKind k | Just k' <- coreView k = isStarKind k' -isStarKind (TyConApp tc [TyConApp ptr_rep []]) - = tc `hasKey` tYPETyConKey - && ptr_rep `hasKey` liftedRepDataConKey -isStarKind _ = False - -- See Note [Kind Constraint and kind *] - --- | Is the tycon @Constraint@? -isStarKindSynonymTyCon :: TyCon -> Bool -isStarKindSynonymTyCon tc = tc `hasKey` constraintKindTyConKey +classifiesTypeWithValues = isTYPE (const True) diff --git a/compiler/types/OptCoercion.hs b/compiler/types/OptCoercion.hs index 67644094ed..8a44b86f7e 100644 --- a/compiler/types/OptCoercion.hs +++ b/compiler/types/OptCoercion.hs @@ -4,14 +4,14 @@ -- The default iteration limit is a bit too low for the definitions -- in this module. -#if __GLASGOW_HASKELL__ >= 800 {-# OPTIONS_GHC -fmax-pmcheck-iterations=10000000 #-} -#endif module OptCoercion ( optCoercion, checkAxInstCo ) where #include "HsVersions.h" +import GhcPrelude + import DynFlags import TyCoRep import Coercion @@ -55,6 +55,7 @@ opt_co2. Note [Optimising InstCo] ~~~~~~~~~~~~~~~~~~~~~~~~ +(1) tv is a type variable When we have (InstCo (ForAllCo tv h g) g2), we want to optimise. Let's look at the typing rules. @@ -74,27 +75,55 @@ We thus want some coercion proving this: (t1[tv |-> s1]) ~ (t2[tv |-> s2 |> sym h]) If we substitute the *type* tv for the *coercion* -(g2 `mkCoherenceRightCo` sym h) in g, we'll get this result exactly. +(g2 ; t2 ~ t2 |> sym h) in g, we'll get this result exactly. This is bizarre, though, because we're substituting a type variable with a coercion. However, this operation already exists: it's called *lifting*, and defined in Coercion. We just need to enhance the lifting operation to be able to deal with an ambient substitution, which is why a LiftingContext stores a TCvSubst. +(2) cv is a coercion variable +Now consider we have (InstCo (ForAllCo cv h g) g2), we want to optimise. + +h : (t1 ~r t2) ~N (t3 ~r t4) +cv : t1 ~r t2 |- g : t1' ~r2 t2' +n1 = nth r 2 (downgradeRole r N h) :: t1 ~r t3 +n2 = nth r 3 (downgradeRole r N h) :: t2 ~r t4 +------------------------------------------------ +ForAllCo cv h g : (all cv:t1 ~r t2. t1') ~r2 + (all cv:t3 ~r t4. t2'[cv |-> n1 ; cv ; sym n2]) + +g1 : (all cv:t1 ~r t2. t1') ~ (all cv: t3 ~r t4. t2') +g2 : h1 ~N h2 +h1 : t1 ~r t2 +h2 : t3 ~r t4 +------------------------------------------------ +InstCo g1 g2 : t1'[cv |-> h1] ~ t2'[cv |-> h2] + +We thus want some coercion proving this: + + t1'[cv |-> h1] ~ t2'[cv |-> n1 ; h2; sym n2] + +So we substitute the coercion variable c for the coercion +(h1 ~N (n1; h2; sym n2)) in g. -} -optCoercion :: TCvSubst -> Coercion -> NormalCo +optCoercion :: DynFlags -> TCvSubst -> Coercion -> NormalCo -- ^ optCoercion applies a substitution to a coercion, -- *and* optimises it to reduce its size -optCoercion env co - | hasNoOptCoercion unsafeGlobalDynFlags = substCo env co +optCoercion dflags env co + | hasNoOptCoercion dflags = substCo env co + | otherwise = optCoercion' env co + +optCoercion' :: TCvSubst -> Coercion -> NormalCo +optCoercion' env co | debugIsOn = let out_co = opt_co1 lc False co (Pair in_ty1 in_ty2, in_role) = coercionKindRole co (Pair out_ty1 out_ty2, out_role) = coercionKindRole out_co in - ASSERT2( substTyUnchecked env in_ty1 `eqType` out_ty1 && - substTyUnchecked env in_ty2 `eqType` out_ty2 && + ASSERT2( substTy env in_ty1 `eqType` out_ty1 && + substTy env in_ty2 `eqType` out_ty2 && in_role == out_role , text "optCoercion changed types!" $$ hang (text "in_co:") 2 (ppr co) @@ -166,12 +195,30 @@ opt_co4_wrap env sym rep r co result -} -opt_co4 env _ rep r (Refl _r ty) +opt_co4 env _ rep r (Refl ty) + = ASSERT2( r == Nominal, text "Expected role:" <+> ppr r $$ + text "Found role:" <+> ppr Nominal $$ + text "Type:" <+> ppr ty ) + liftCoSubst (chooseRole rep r) env ty + +opt_co4 env _ rep r (GRefl _r ty MRefl) = ASSERT2( r == _r, text "Expected role:" <+> ppr r $$ text "Found role:" <+> ppr _r $$ text "Type:" <+> ppr ty ) liftCoSubst (chooseRole rep r) env ty +opt_co4 env sym rep r (GRefl _r ty (MCo co)) + = ASSERT2( r == _r, text "Expected role:" <+> ppr r $$ + text "Found role:" <+> ppr _r $$ + text "Type:" <+> ppr ty ) + if isGReflCo co || isGReflCo co' + then liftCoSubst r' env ty + else wrapSym sym $ mkCoherenceRightCo r' ty' co' (liftCoSubst r' env ty) + where + r' = chooseRole rep r + ty' = substTy (lcSubstLeft env) ty + co' = opt_co4 env False False Nominal co + opt_co4 env sym rep r (SymCo co) = opt_co4_wrap env (not sym) rep r co -- surprisingly, we don't have to do anything to the env here. This is -- because any "lifting" substitutions in the env are tied to ForAllCos, @@ -221,7 +268,7 @@ opt_co4 env sym rep r (CoVarCo cv) = opt_co4_wrap (zapLiftingContext env) sym rep r co | ty1 `eqType` ty2 -- See Note [Optimise CoVarCo to Refl] - = Refl (chooseRole rep r) ty1 + = mkReflCo (chooseRole rep r) ty1 | otherwise = ASSERT( isCoVar cv1 ) @@ -238,6 +285,8 @@ opt_co4 env sym rep r (CoVarCo cv) cv -- cv1 might have a substituted kind! +opt_co4 _ _ _ _ (HoleCo h) + = pprPanic "opt_univ fell into a hole" (ppr h) opt_co4 env sym rep r (AxiomInstCo con ind cos) -- Do *not* push sym inside top-level axioms @@ -267,8 +316,44 @@ opt_co4 env sym rep r (TransCo co1 co2) co2' = opt_co4_wrap env sym rep r co2 in_scope = lcInScopeSet env +opt_co4 env _sym rep r (NthCo _r n co) + | Just (ty, _) <- isReflCo_maybe co + , Just (_tc, args) <- ASSERT( r == _r ) + splitTyConApp_maybe ty + = liftCoSubst (chooseRole rep r) env (args `getNth` n) + | Just (ty, _) <- isReflCo_maybe co + , n == 0 + , Just (tv, _) <- splitForAllTy_maybe ty + -- works for both tyvar and covar + = liftCoSubst (chooseRole rep r) env (varType tv) + +opt_co4 env sym rep r (NthCo r1 n (TyConAppCo _ _ cos)) + = ASSERT( r == r1 ) + opt_co4_wrap env sym rep r (cos `getNth` n) + +opt_co4 env sym rep r (NthCo _r n (ForAllCo _ eta _)) + -- works for both tyvar and covar + = ASSERT( r == _r ) + ASSERT( n == 0 ) + opt_co4_wrap env sym rep Nominal eta + +opt_co4 env sym rep r (NthCo _r n co) + | TyConAppCo _ _ cos <- co' + , let nth_co = cos `getNth` n + = if rep && (r == Nominal) + -- keep propagating the SubCo + then opt_co4_wrap (zapLiftingContext env) False True Nominal nth_co + else nth_co + + | ForAllCo _ eta _ <- co' + = if rep + then opt_co4_wrap (zapLiftingContext env) False True Nominal eta + else eta -opt_co4 env sym rep r co@(NthCo {}) = opt_nth_co env sym rep r co + | otherwise + = wrapRole rep r $ NthCo r n co' + where + co' = opt_co1 env sym co opt_co4 env sym rep r (LRCo lr co) | Just pr_co <- splitAppCo_maybe co @@ -290,41 +375,58 @@ opt_co4 env sym rep r (LRCo lr co) -- See Note [Optimising InstCo] opt_co4 env sym rep r (InstCo co1 arg) -- forall over type... - | Just (tv, kind_co, co_body) <- splitForAllCo_maybe co1 + | Just (tv, kind_co, co_body) <- splitForAllCo_ty_maybe co1 = opt_co4_wrap (extendLiftingContext env tv - (arg' `mkCoherenceRightCo` mkSymCo kind_co)) + (mkCoherenceRightCo Nominal t2 (mkSymCo kind_co) arg')) + -- kind_co :: k1 ~ k2 + -- arg' :: (t1 :: k1) ~ (t2 :: k2) + -- tv |-> (t1 :: k1) ~ (((t2 :: k2) |> (sym kind_co)) :: k1) sym rep r co_body + -- forall over coercion... + | Just (cv, kind_co, co_body) <- splitForAllCo_co_maybe co1 + , CoercionTy h1 <- t1 + , CoercionTy h2 <- t2 + = let new_co = mk_new_co cv (opt_co4_wrap env sym False Nominal kind_co) h1 h2 + in opt_co4_wrap (extendLiftingContext env cv new_co) sym rep r co_body + -- See if it is a forall after optimization -- If so, do an inefficient one-variable substitution, then re-optimize -- forall over type... - | Just (tv', kind_co', co_body') <- splitForAllCo_maybe co1' + | Just (tv', kind_co', co_body') <- splitForAllCo_ty_maybe co1' = opt_co4_wrap (extendLiftingContext (zapLiftingContext env) tv' - (arg' `mkCoherenceRightCo` mkSymCo kind_co')) + (mkCoherenceRightCo Nominal t2 (mkSymCo kind_co') arg')) False False r' co_body' + -- forall over coercion... + | Just (cv', kind_co', co_body') <- splitForAllCo_co_maybe co1' + , CoercionTy h1 <- t1 + , CoercionTy h2 <- t2 + = let new_co = mk_new_co cv' kind_co' h1 h2 + in opt_co4_wrap (extendLiftingContext (zapLiftingContext env) cv' new_co) + False False r' co_body' + | otherwise = InstCo co1' arg' where co1' = opt_co4_wrap env sym rep r co1 r' = chooseRole rep r arg' = opt_co4_wrap env sym False Nominal arg - -opt_co4 env sym rep r (CoherenceCo co1 co2) - | TransCo col1 cor1 <- co1 - = opt_co4_wrap env sym rep r (mkTransCo (mkCoherenceCo col1 co2) cor1) - - | TransCo col1' cor1' <- co1' - = if sym then opt_trans in_scope col1' - (optCoercion (zapTCvSubst (lcTCvSubst env)) - (mkCoherenceRightCo cor1' co2')) - else opt_trans in_scope (mkCoherenceCo col1' co2') cor1' - - | otherwise - = wrapSym sym $ mkCoherenceCo (opt_co4_wrap env False rep r co1) co2' - where co1' = opt_co4_wrap env sym rep r co1 - co2' = opt_co4_wrap env False False Nominal co2 - in_scope = lcInScopeSet env + Pair t1 t2 = coercionKind arg' + + mk_new_co cv kind_co h1 h2 + = let -- h1 :: (t1 ~ t2) + -- h2 :: (t3 ~ t4) + -- kind_co :: (t1 ~ t2) ~ (t3 ~ t4) + -- n1 :: t1 ~ t3 + -- n2 :: t2 ~ t4 + -- new_co = (h1 :: t1 ~ t2) ~ ((n1;h2;sym n2) :: t1 ~ t2) + r2 = coVarRole cv + kind_co' = downgradeRole r2 Nominal kind_co + n1 = mkNthCo r2 2 kind_co' + n2 = mkNthCo r2 3 kind_co' + in mkProofIrrelCo Nominal (Refl (coercionType h1)) h1 + (n1 `mkTransCo` h2 `mkTransCo` (mkSymCo n2)) opt_co4 env sym _rep r (KindCo co) = ASSERT( r == Nominal ) @@ -396,25 +498,43 @@ opt_univ env sym prov role oty1 oty2 -- NB: prov must not be the two interesting ones (ProofIrrel & Phantom); -- Phantom is already taken care of, and ProofIrrel doesn't relate tyconapps = let roles = tyConRolesX role tc1 - arg_cos = zipWith3 (mkUnivCo prov) roles tys1 tys2 + arg_cos = zipWith3 (mkUnivCo prov') roles tys1 tys2 arg_cos' = zipWith (opt_co4 env sym False) roles arg_cos in mkTyConAppCo role tc1 arg_cos' -- can't optimize the AppTy case because we can't build the kind coercions. - | Just (tv1, ty1) <- splitForAllTy_maybe oty1 - , Just (tv2, ty2) <- splitForAllTy_maybe oty2 + | Just (tv1, ty1) <- splitForAllTy_ty_maybe oty1 + , Just (tv2, ty2) <- splitForAllTy_ty_maybe oty2 -- NB: prov isn't interesting here either = let k1 = tyVarKind tv1 k2 = tyVarKind tv2 - eta = mkUnivCo prov Nominal k1 k2 + eta = mkUnivCo prov' Nominal k1 k2 -- eta gets opt'ed soon, but not yet. ty2' = substTyWith [tv2] [TyVarTy tv1 `mkCastTy` eta] ty2 (env', tv1', eta') = optForAllCoBndr env sym tv1 eta in - mkForAllCo tv1' eta' (opt_univ env' sym prov role ty1 ty2') + mkForAllCo tv1' eta' (opt_univ env' sym prov' role ty1 ty2') + + | Just (cv1, ty1) <- splitForAllTy_co_maybe oty1 + , Just (cv2, ty2) <- splitForAllTy_co_maybe oty2 + -- NB: prov isn't interesting here either + = let k1 = varType cv1 + k2 = varType cv2 + r' = coVarRole cv1 + eta = mkUnivCo prov' Nominal k1 k2 + eta_d = downgradeRole r' Nominal eta + -- eta gets opt'ed soon, but not yet. + n_co = (mkSymCo $ mkNthCo r' 2 eta_d) `mkTransCo` + (mkCoVarCo cv1) `mkTransCo` + (mkNthCo r' 3 eta_d) + ty2' = substTyWithCoVars [cv2] [n_co] ty2 + + (env', cv1', eta') = optForAllCoBndr env sym cv1 eta + in + mkForAllCo cv1' eta' (opt_univ env' sym prov' role ty1 ty2') | otherwise = let ty1 = substTyUnchecked (lcSubstLeft env) oty1 @@ -430,64 +550,6 @@ opt_univ env sym prov role oty1 oty2 PhantomProv kco -> PhantomProv $ opt_co4_wrap env sym False Nominal kco ProofIrrelProv kco -> ProofIrrelProv $ opt_co4_wrap env sym False Nominal kco PluginProv _ -> prov - HoleProv h -> pprPanic "opt_univ fell into a hole" (ppr h) - - -------------- --- NthCo must be handled separately, because it's the one case where we can't --- tell quickly what the component coercion's role is from the containing --- coercion. To avoid repeated coercionRole calls as opt_co1 calls opt_co2, --- we just look for nested NthCo's, which can happen in practice. -opt_nth_co :: LiftingContext -> SymFlag -> ReprFlag -> Role -> Coercion -> NormalCo -opt_nth_co env sym rep r = go [] - where - go ns (NthCo n co) = go (n:ns) co - -- previous versions checked if the tycon is decomposable. This - -- is redundant, because a non-decomposable tycon under an NthCo - -- is entirely bogus. See docs/core-spec/core-spec.pdf. - go ns co - = opt_nths ns co - - -- try to resolve 1 Nth - push_nth n (Refl r1 ty) - | Just (tc, args) <- splitTyConApp_maybe ty - = Just (Refl (nthRole r1 tc n) (args `getNth` n)) - | n == 0 - , Just (tv, _) <- splitForAllTy_maybe ty - = Just (Refl Nominal (tyVarKind tv)) - push_nth n (TyConAppCo _ _ cos) - = Just (cos `getNth` n) - push_nth 0 (ForAllCo _ eta _) - = Just eta - push_nth _ _ = Nothing - - -- input coercion is *not* yet sym'd or opt'd - opt_nths [] co = opt_co4_wrap env sym rep r co - opt_nths (n:ns) co - | Just co' <- push_nth n co - = opt_nths ns co' - - -- here, the co isn't a TyConAppCo, so we opt it, hoping to get - -- a TyConAppCo as output. We don't know the role, so we use - -- opt_co1. This is slightly annoying, because opt_co1 will call - -- coercionRole, but as long as we don't have a long chain of - -- NthCo's interspersed with some other coercion former, we should - -- be OK. - opt_nths ns co = opt_nths' ns (opt_co1 env sym co) - - -- input coercion *is* sym'd and opt'd - opt_nths' [] co - = if rep && (r == Nominal) - -- propagate the SubCo: - then opt_co4_wrap (zapLiftingContext env) False True r co - else co - opt_nths' (n:ns) co - | Just co' <- push_nth n co - = opt_nths' ns co' - opt_nths' ns co = wrapRole rep r (mk_nths ns co) - - mk_nths [] co = co - mk_nths (n:ns) co = mk_nths ns (mkNthCo n co) ------------- opt_transList :: InScopeSet -> [NormalCo] -> [NormalCo] -> [NormalCo] @@ -496,12 +558,14 @@ opt_transList is = zipWith (opt_trans is) opt_trans :: InScopeSet -> NormalCo -> NormalCo -> NormalCo opt_trans is co1 co2 | isReflCo co1 = co2 + -- optimize when co1 is a Refl Co | otherwise = opt_trans1 is co1 co2 opt_trans1 :: InScopeSet -> NormalNonIdCo -> NormalCo -> NormalCo -- First arg is not the identity opt_trans1 is co1 co2 | isReflCo co2 = co1 + -- optimize when co2 is a Refl Co | otherwise = opt_trans2 is co1 co2 opt_trans2 :: InScopeSet -> NormalNonIdCo -> NormalNonIdCo -> NormalCo @@ -527,12 +591,19 @@ opt_trans2 _ co1 co2 -- Optimize coercions with a top-level use of transitivity. opt_trans_rule :: InScopeSet -> NormalNonIdCo -> NormalNonIdCo -> Maybe NormalCo +opt_trans_rule is in_co1@(GRefl r1 t1 (MCo co1)) in_co2@(GRefl r2 _ (MCo co2)) + = ASSERT( r1 == r2 ) + fireTransRule "GRefl" in_co1 in_co2 $ + mkGReflRightCo r1 t1 (opt_trans is co1 co2) + -- Push transitivity through matching destructors -opt_trans_rule is in_co1@(NthCo d1 co1) in_co2@(NthCo d2 co2) +opt_trans_rule is in_co1@(NthCo r1 d1 co1) in_co2@(NthCo r2 d2 co2) | d1 == d2 + , coercionRole co1 == coercionRole co2 , co1 `compatible_co` co2 - = fireTransRule "PushNth" in_co1 in_co2 $ - mkNthCo d1 (opt_trans is co1 co2) + = ASSERT( r1 == r2 ) + fireTransRule "PushNth" in_co1 in_co2 $ + mkNthCo r1 d1 (opt_trans is co1 co2) opt_trans_rule is in_co1@(LRCo d1 co1) in_co2@(LRCo d2 co2) | d1 == d2 @@ -576,9 +647,8 @@ opt_trans_rule is in_co1@(FunCo r1 co1a co1b) in_co2@(FunCo r2 co2a co2b) mkFunCo r1 (opt_trans is co1a co2a) (opt_trans is co1b co2b) 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) + -- Must call opt_trans_rule_app; see Note [EtaAppCo] + = opt_trans_rule_app is in_co1 in_co2 co1a [co1b] co2a [co2b] -- Eta rules opt_trans_rule is co1@(TyConAppCo r tc cos1) co2 @@ -595,33 +665,67 @@ opt_trans_rule is co1 co2@(TyConAppCo r tc 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_app is co1 co2 co1a [co1b] co2a [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) + = opt_trans_rule_app is co1 co2 co1a [co1b] co2a [co2b] -- Push transitivity inside forall +-- forall over types. opt_trans_rule is co1 co2 - | ForAllCo tv1 eta1 r1 <- co1 - , Just (tv2,eta2,r2) <- etaForAllCo_maybe co2 + | Just (tv1, eta1, r1) <- splitForAllCo_ty_maybe co1 + , Just (tv2, eta2, r2) <- etaForAllCo_ty_maybe co2 = push_trans tv1 eta1 r1 tv2 eta2 r2 - | ForAllCo tv2 eta2 r2 <- co2 - , Just (tv1,eta1,r1) <- etaForAllCo_maybe co1 + | Just (tv2, eta2, r2) <- splitForAllCo_ty_maybe co2 + , Just (tv1, eta1, r1) <- etaForAllCo_ty_maybe co1 = push_trans tv1 eta1 r1 tv2 eta2 r2 where push_trans tv1 eta1 r1 tv2 eta2 r2 - = fireTransRule "EtaAllTy" co1 co2 $ + -- Given: + -- co1 = /\ tv1 : eta1. r1 + -- co2 = /\ tv2 : eta2. r2 + -- Wanted: + -- /\tv1 : (eta1;eta2). (r1; r2[tv2 |-> tv1 |> eta1]) + = fireTransRule "EtaAllTy_ty" co1 co2 $ mkForAllCo tv1 (opt_trans is eta1 eta2) (opt_trans is' r1 r2') where is' = is `extendInScopeSet` tv1 - r2' = substCoWithUnchecked [tv2] [TyVarTy tv1] r2 + r2' = substCoWithUnchecked [tv2] [mkCastTy (TyVarTy tv1) eta1] r2 + +-- Push transitivity inside forall +-- forall over coercions. +opt_trans_rule is co1 co2 + | Just (cv1, eta1, r1) <- splitForAllCo_co_maybe co1 + , Just (cv2, eta2, r2) <- etaForAllCo_co_maybe co2 + = push_trans cv1 eta1 r1 cv2 eta2 r2 + + | Just (cv2, eta2, r2) <- splitForAllCo_co_maybe co2 + , Just (cv1, eta1, r1) <- etaForAllCo_co_maybe co1 + = push_trans cv1 eta1 r1 cv2 eta2 r2 + + where + push_trans cv1 eta1 r1 cv2 eta2 r2 + -- Given: + -- co1 = /\ cv1 : eta1. r1 + -- co2 = /\ cv2 : eta2. r2 + -- Wanted: + -- n1 = nth 2 eta1 + -- n2 = nth 3 eta1 + -- nco = /\ cv1 : (eta1;eta2). (r1; r2[cv2 |-> (sym n1);cv1;n2]) + = fireTransRule "EtaAllTy_co" co1 co2 $ + mkForAllCo cv1 (opt_trans is eta1 eta2) (opt_trans is' r1 r2') + where + is' = is `extendInScopeSet` cv1 + role = coVarRole cv1 + eta1' = downgradeRole role Nominal eta1 + n1 = mkNthCo role 2 eta1' + n2 = mkNthCo role 3 eta1' + r2' = substCo (zipCvSubst [cv2] [(mkSymCo n1) `mkTransCo` + (mkCoVarCo cv1) `mkTransCo` n2]) + r2 -- Push transitivity inside axioms opt_trans_rule is co1 co2 @@ -682,25 +786,56 @@ opt_trans_rule is co1 co2 co2_is_axiom_maybe = isAxiom_maybe co2 role = coercionRole co1 -- should be the same as coercionRole co2! -opt_trans_rule is co1 co2 - | Just (lco, lh) <- isCohRight_maybe co1 - , Just (rco, rh) <- isCohLeft_maybe co2 - , (coercionType lh) `eqType` (coercionType rh) - = opt_trans_rule is lco rco - opt_trans_rule _ co1 co2 -- Identity rule | (Pair ty1 _, r) <- coercionKindRole co1 , Pair _ ty2 <- coercionKind co2 , ty1 `eqType` ty2 = fireTransRule "RedTypeDirRefl" co1 co2 $ - Refl r ty2 + mkReflCo r ty2 opt_trans_rule _ _ _ = Nothing +-- See Note [EtaAppCo] +opt_trans_rule_app :: InScopeSet + -> Coercion -- original left-hand coercion (printing only) + -> Coercion -- original right-hand coercion (printing only) + -> Coercion -- left-hand coercion "function" + -> [Coercion] -- left-hand coercion "args" + -> Coercion -- right-hand coercion "function" + -> [Coercion] -- right-hand coercion "args" + -> Maybe Coercion +opt_trans_rule_app is orig_co1 orig_co2 co1a co1bs co2a co2bs + | AppCo co1aa co1ab <- co1a + , Just (co2aa, co2ab) <- etaAppCo_maybe co2a + = opt_trans_rule_app is orig_co1 orig_co2 co1aa (co1ab:co1bs) co2aa (co2ab:co2bs) + + | AppCo co2aa co2ab <- co2a + , Just (co1aa, co1ab) <- etaAppCo_maybe co1a + = opt_trans_rule_app is orig_co1 orig_co2 co1aa (co1ab:co1bs) co2aa (co2ab:co2bs) + + | otherwise + = ASSERT( co1bs `equalLength` co2bs ) + fireTransRule ("EtaApps:" ++ show (length co1bs)) orig_co1 orig_co2 $ + let Pair _ rt1a = coercionKind co1a + (Pair lt2a _, rt2a) = coercionKindRole co2a + + Pair _ rt1bs = traverse coercionKind co1bs + Pair lt2bs _ = traverse coercionKind co2bs + rt2bs = map coercionRole co2bs + + kcoa = mkKindCo $ buildCoercion lt2a rt1a + kcobs = map mkKindCo $ zipWith buildCoercion lt2bs rt1bs + + co2a' = mkCoherenceLeftCo rt2a lt2a kcoa co2a + co2bs' = zipWith3 mkGReflLeftCo rt2bs lt2bs kcobs + co2bs'' = zipWith mkTransCo co2bs' co2bs + in + mkAppCos (opt_trans is co1a co2a') + (zipWith (opt_trans is) co1bs co2bs'') + fireTransRule :: String -> Coercion -> Coercion -> Coercion -> Maybe Coercion fireTransRule _rule _co1 _co2 res - = -- pprTrace ("Trans rule fired: " ++ _rule) (vcat [ppr _co1, ppr _co2, ppr res]) $ - Just res + = Just res {- Note [Conflict checking with AxiomInstCo] @@ -757,6 +892,64 @@ that (Id Int) and (Id Bool) are Surely Apart, as they're headed by type families. At the time of writing, I (Richard Eisenberg) couldn't think of a way of detecting this any more efficient than just building the optimised coercion and checking. + +Note [EtaAppCo] +~~~~~~~~~~~~~~~ +Suppose we're trying to optimize (co1a co1b ; co2a co2b). Ideally, we'd +like to rewrite this to (co1a ; co2a) (co1b ; co2b). The problem is that +the resultant coercions might not be well kinded. Here is an example (things +labeled with x don't matter in this example): + + k1 :: Type + k2 :: Type + + a :: k1 -> Type + b :: k1 + + h :: k1 ~ k2 + + co1a :: x1 ~ (a |> (h -> <Type>) + co1b :: x2 ~ (b |> h) + + co2a :: a ~ x3 + co2b :: b ~ x4 + +First, convince yourself of the following: + + co1a co1b :: x1 x2 ~ (a |> (h -> <Type>)) (b |> h) + co2a co2b :: a b ~ x3 x4 + + (a |> (h -> <Type>)) (b |> h) `eqType` a b + +That last fact is due to Note [Non-trivial definitional equality] in TyCoRep, +where we ignore coercions in types as long as two types' kinds are the same. +In our case, we meet this last condition, because + + (a |> (h -> <Type>)) (b |> h) :: Type + and + a b :: Type + +So the input coercion (co1a co1b ; co2a co2b) is well-formed. But the +suggested output coercions (co1a ; co2a) and (co1b ; co2b) are not -- the +kinds don't match up. + +The solution here is to twiddle the kinds in the output coercions. First, we +need to find coercions + + ak :: kind(a |> (h -> <Type>)) ~ kind(a) + bk :: kind(b |> h) ~ kind(b) + +This can be done with mkKindCo and buildCoercion. The latter assumes two +types are identical modulo casts and builds a coercion between them. + +Then, we build (co1a ; co2a |> sym ak) and (co1b ; co2b |> sym bk) as the +output coercions. These are well-kinded. + +Also, note that all of this is done after accumulated any nested AppCo +parameters. This step is to avoid quadratic behavior in calling coercionKind. + +The problem described here was first found in dependent/should_compile/dynamic-paper. + -} -- | Check to make sure that an AxInstCo is internally consistent. @@ -839,18 +1032,6 @@ matchAxiom sym ax@(CoAxiom { co_ax_tc = tc }) ind co = Nothing ------------- --- destruct a CoherenceCo -isCohLeft_maybe :: Coercion -> Maybe (Coercion, Coercion) -isCohLeft_maybe (CoherenceCo co1 co2) = Just (co1, co2) -isCohLeft_maybe _ = Nothing - --- destruct a (sym (co1 |> co2)). --- if isCohRight_maybe co = Just (co1, co2), then (sym co1) `mkCohRightCo` co2 = co -isCohRight_maybe :: Coercion -> Maybe (Coercion, Coercion) -isCohRight_maybe (SymCo (CoherenceCo co1 co2)) = Just (mkSymCo co1, co2) -isCohRight_maybe _ = Nothing - -------------- compatible_co :: Coercion -> Coercion -> Bool -- Check whether (co1 . co2) will be well-kinded compatible_co co1 co2 @@ -861,42 +1042,83 @@ compatible_co co1 co2 ------------- {- -etaForAllCo_maybe +etaForAllCo ~~~~~~~~~~~~~~~~~ +(1) etaForAllCo_ty_maybe Suppose we have g : all a1:k1.t1 ~ all a2:k2.t2 but g is *not* a ForAllCo. We want to eta-expand it. So, we do this: - g' = all a1:(ForAllKindCo g).(InstCo g (a1 `mkCoherenceRightCo` ForAllKindCo g)) + g' = all a1:(ForAllKindCo g).(InstCo g (a1 ~ a1 |> ForAllKindCo g)) Call the kind coercion h1 and the body coercion h2. We can see that - h2 : t1 ~ t2[a2 |-> (a1 |> h2)] + h2 : t1 ~ t2[a2 |-> (a1 |> h1)] According to the typing rule for ForAllCo, we get that - g' : all a1:k1.t1 ~ all a1:k2.(t2[a2 |-> (a1 |> h2)][a1 |-> a1 |> sym h2]) + g' : all a1:k1.t1 ~ all a1:k2.(t2[a2 |-> (a1 |> h1)][a1 |-> a1 |> sym h1]) or g' : all a1:k1.t1 ~ all a1:k2.(t2[a2 |-> a1]) as desired. + +(2) etaForAllCo_co_maybe +Suppose we have + + g : all c1:(s1~s2). t1 ~ all c2:(s3~s4). t2 + +Similarly, we do this + + g' = all c1:h1. h2 + : all c1:(s1~s2). t1 ~ all c1:(s3~s4). t2[c2 |-> (sym eta1;c1;eta2)] + [c1 |-> eta1;c1;sym eta2] + +Here, + + h1 = mkNthCo Nominal 0 g :: (s1~s2)~(s3~s4) + eta1 = mkNthCo r 2 h1 :: (s1 ~ s3) + eta2 = mkNthCo r 3 h1 :: (s2 ~ s4) + h2 = mkInstCo g (cv1 ~ (sym eta1;c1;eta2)) -} -etaForAllCo_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion) +etaForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion) -- Try to make the coercion be of form (forall tv:kind_co. co) -etaForAllCo_maybe co - | ForAllCo tv kind_co r <- co +etaForAllCo_ty_maybe co + | Just (tv, kind_co, r) <- splitForAllCo_ty_maybe co = Just (tv, kind_co, r) | Pair ty1 ty2 <- coercionKind co - , Just (tv1, _) <- splitForAllTy_maybe ty1 - , isForAllTy ty2 - , let kind_co = mkNthCo 0 co + , Just (tv1, _) <- splitForAllTy_ty_maybe ty1 + , isForAllTy_ty ty2 + , let kind_co = mkNthCo Nominal 0 co = Just ( tv1, kind_co - , mkInstCo co (mkNomReflCo (TyVarTy tv1) `mkCoherenceRightCo` kind_co) ) + , mkInstCo co (mkGReflRightCo Nominal (TyVarTy tv1) kind_co)) + + | otherwise + = Nothing + +etaForAllCo_co_maybe :: Coercion -> Maybe (CoVar, Coercion, Coercion) +-- Try to make the coercion be of form (forall cv:kind_co. co) +etaForAllCo_co_maybe co + | Just (cv, kind_co, r) <- splitForAllCo_co_maybe co + = Just (cv, kind_co, r) + + | Pair ty1 ty2 <- coercionKind co + , Just (cv1, _) <- splitForAllTy_co_maybe ty1 + , isForAllTy_co ty2 + = let kind_co = mkNthCo Nominal 0 co + r = coVarRole cv1 + l_co = mkCoVarCo cv1 + kind_co' = downgradeRole r Nominal kind_co + r_co = (mkSymCo (mkNthCo r 2 kind_co')) `mkTransCo` + l_co `mkTransCo` + (mkNthCo r 3 kind_co') + in Just ( cv1, kind_co + , mkInstCo co (mkProofIrrelCo Nominal kind_co l_co r_co)) | otherwise = Nothing @@ -933,9 +1155,11 @@ etaTyConAppCo_maybe tc co , tc1 == tc2 , isInjectiveTyCon tc r -- See Note [NthCo and newtypes] in TyCoRep , let n = length tys1 + , tys2 `lengthIs` n -- This can fail in an erroneous progam + -- E.g. T a ~# T a b + -- Trac #14607 = ASSERT( tc == tc1 ) - ASSERT( tys2 `lengthIs` n ) - Just (decomposeCo n co) + Just (decomposeCo n co (tyConRolesX r tc1)) -- NB: n might be <> tyConArity tc -- e.g. data family T a :: * -> * -- g :: T a b ~ T c d @@ -968,6 +1192,6 @@ and these two imply -} optForAllCoBndr :: LiftingContext -> Bool - -> TyVar -> Coercion -> (LiftingContext, TyVar, Coercion) + -> TyCoVar -> Coercion -> (LiftingContext, TyCoVar, Coercion) optForAllCoBndr env sym - = substForAllCoBndrCallbackLC sym (opt_co4_wrap env sym False Nominal) env + = substForAllCoBndrUsingLC sym (opt_co4_wrap env sym False Nominal) env diff --git a/compiler/types/TyCoRep.hs b/compiler/types/TyCoRep.hs index 5ac63e5b04..b50327fc37 100644 --- a/compiler/types/TyCoRep.hs +++ b/compiler/types/TyCoRep.hs @@ -18,7 +18,6 @@ Note [The Type-related module hierarchy] -- We expose the relevant stuff from this module via the Type module {-# OPTIONS_HADDOCK hide #-} {-# LANGUAGE CPP, DeriveDataTypeable, MultiWayIf #-} -{-# LANGUAGE ImplicitParams #-} module TyCoRep ( TyThing(..), tyThingCategory, pprTyThingCategory, pprShortTyThing, @@ -27,45 +26,55 @@ module TyCoRep ( Type(..), TyLit(..), KindOrType, Kind, + KnotTied, PredType, ThetaType, -- Synonyms ArgFlag(..), -- * Coercions Coercion(..), - UnivCoProvenance(..), CoercionHole(..), + UnivCoProvenance(..), + CoercionHole(..), coHoleCoVar, setCoHoleCoVar, CoercionN, CoercionR, CoercionP, KindCoercion, + MCoercion(..), MCoercionR, MCoercionN, -- * Functions over types mkTyConTy, mkTyVarTy, mkTyVarTys, - mkFunTy, mkFunTys, mkForAllTy, mkForAllTys, - mkPiTy, mkPiTys, + mkTyCoVarTy, mkTyCoVarTys, + mkFunTy, mkFunTys, mkTyCoForAllTy, mkForAllTys, + mkForAllTy, + mkTyCoPiTy, mkTyCoPiTys, + mkPiTys, + isTYPE, isLiftedTypeKind, isUnliftedTypeKind, isCoercionType, isRuntimeRepTy, isRuntimeRepVar, - isRuntimeRepKindedTy, dropRuntimeRepArgs, sameVis, -- * Functions over binders - TyBinder(..), TyVarBinder, - binderVar, binderVars, binderKind, binderArgFlag, + TyCoBinder(..), TyCoVarBinder, TyBinder, + binderVar, binderVars, binderType, binderArgFlag, delBinderVar, isInvisibleArgFlag, isVisibleArgFlag, isInvisibleBinder, isVisibleBinder, + isTyBinder, -- * Functions over coercions pickLR, -- * Pretty-printing pprType, pprParendType, pprPrecType, - pprTypeApp, pprTvBndr, pprTvBndrs, + pprTypeApp, pprTCvBndr, pprTCvBndrs, pprSigmaType, pprTheta, pprParendTheta, pprForAll, pprUserForAll, pprTyVar, pprTyVars, pprThetaArrowTy, pprClassPred, pprKind, pprParendKind, pprTyLit, - TyPrec(..), maybeParen, pprTcAppCo, - pprPrefixApp, pprArrowChain, + PprPrec(..), topPrec, sigPrec, opPrec, funPrec, appPrec, maybeParen, pprDataCons, ppSuggestExplicitKinds, + pprCo, pprParendCo, + + debugPprType, + -- * Free variables tyCoVarsOfType, tyCoVarsOfTypeDSet, tyCoVarsOfTypes, tyCoVarsOfTypesDSet, tyCoFVsBndr, tyCoFVsOfType, tyCoVarsOfTypeList, @@ -78,6 +87,7 @@ module TyCoRep ( tyCoFVsOfCo, tyCoFVsOfCos, tyCoVarsOfCoList, tyCoVarsOfProv, closeOverKinds, + injectiveVarsOfBinder, injectiveVarsOfType, noFreeVarsOfType, noFreeVarsOfCo, @@ -85,18 +95,20 @@ module TyCoRep ( TCvSubst(..), TvSubstEnv, CvSubstEnv, emptyTvSubstEnv, emptyCvSubstEnv, composeTCvSubstEnv, composeTCvSubst, emptyTCvSubst, mkEmptyTCvSubst, isEmptyTCvSubst, - mkTCvSubst, mkTvSubst, + mkTCvSubst, mkTvSubst, mkCvSubst, getTvSubstEnv, getCvSubstEnv, getTCvInScope, getTCvSubstRangeFVs, isInScope, notElemTCvSubst, setTvSubstEnv, setCvSubstEnv, zapTCvSubst, extendTCvInScope, extendTCvInScopeList, extendTCvInScopeSet, - extendTCvSubst, + extendTCvSubst, extendTCvSubstWithClone, extendCvSubst, extendCvSubstWithClone, - extendTvSubst, extendTvSubstBinder, extendTvSubstWithClone, + extendTvSubst, extendTvSubstBinderAndInScope, extendTvSubstWithClone, extendTvSubstList, extendTvSubstAndInScope, + extendTCvSubstList, unionTCvSubst, zipTyEnv, zipCoEnv, mkTyCoInScopeSet, zipTvSubst, zipCvSubst, + zipTCvSubst, mkTvSubstPrs, substTyWith, substTyWithCoVars, substTysWith, substTysWithCoVars, @@ -107,25 +119,28 @@ module TyCoRep ( substCoUnchecked, substCoWithUnchecked, substTyWithInScope, substTys, substTheta, - lookupTyVar, substTyVarBndr, + lookupTyVar, substCo, substCos, substCoVar, substCoVars, lookupCoVar, - substCoVarBndr, cloneTyVarBndr, cloneTyVarBndrs, - substTyVar, substTyVars, + cloneTyVarBndr, cloneTyVarBndrs, + substVarBndr, substVarBndrs, + substTyVarBndr, substTyVarBndrs, + substCoVarBndr, + substTyVar, substTyVars, substTyCoVars, substForAllCoBndr, - substTyVarBndrCallback, substForAllCoBndrCallback, + substVarBndrUsing, substForAllCoBndrUsing, checkValidSubst, isValidTCvSubst, -- * Tidying type related things up for printing tidyType, tidyTypes, tidyOpenType, tidyOpenTypes, tidyOpenKind, - tidyTyCoVarBndr, tidyTyCoVarBndrs, tidyFreeTyCoVars, + tidyVarBndr, tidyVarBndrs, tidyFreeTyCoVars, tidyOpenTyCoVar, tidyOpenTyCoVars, - tidyTyVarOcc, + tidyTyCoVarOcc, tidyTopType, tidyKind, tidyCo, tidyCos, - tidyTyVarBinder, tidyTyVarBinders, + tidyTyCoVarBinder, tidyTyCoVarBinders, -- * Sizes typeSize, coercionSize, provSize @@ -133,19 +148,22 @@ module TyCoRep ( #include "HsVersions.h" +import GhcPrelude + import {-# SOURCE #-} DataCon( dataConFullSig - , dataConUnivTyVarBinders, dataConExTyVarBinders - , DataCon, filterEqSpec ) + , dataConUserTyVarBinders + , DataCon ) import {-# SOURCE #-} Type( isPredTy, isCoercionTy, mkAppTy, mkCastTy - , tyCoVarsOfTypesWellScoped , tyCoVarsOfTypeWellScoped - , coreView, typeKind ) + , tyCoVarsOfTypesWellScoped + , toposortTyVars + , coreView ) -- Transitively pulls in a LOT of stuff, better to break the loop import {-# SOURCE #-} Coercion import {-# SOURCE #-} ConLike ( ConLike(..), conLikeName ) import {-# SOURCE #-} ToIface( toIfaceTypeX, toIfaceTyLit, toIfaceForAllBndr - , toIfaceTyCon, toIfaceTcArgs, toIfaceCoercion ) + , toIfaceTyCon, toIfaceTcArgs, toIfaceCoercionX ) -- friends: import IfaceType @@ -159,7 +177,8 @@ import CoAxiom import FV -- others -import BasicTypes ( LeftOrRight(..), TyPrec(..), maybeParen, pickLR ) +import BasicTypes ( LeftOrRight(..), PprPrec(..), topPrec, sigPrec, opPrec + , funPrec, appPrec, maybeParen, pickLR ) import PrelNames import Outputable import DynFlags @@ -258,8 +277,10 @@ data Type Type Type -- ^ Type application to something other than a 'TyCon'. Parameters: -- - -- 1) Function: must /not/ be a 'TyConApp', + -- 1) Function: must /not/ be a 'TyConApp' or 'CastTy', -- must be another 'AppTy', or 'TyVarTy' + -- See Note [Respecting definitional equality] (EQ1) about the + -- no 'CastTy' requirement -- -- 2) Argument type @@ -281,7 +302,7 @@ data Type -- can appear as the right hand side of a type synonym. | ForAllTy - {-# UNPACK #-} !TyVarBinder + {-# UNPACK #-} !TyCoVarBinder Type -- ^ A Πtype. | FunTy Type Type -- ^ t1 -> t2 Very common, so an important special case @@ -292,8 +313,8 @@ data Type Type KindCoercion -- ^ A kind cast. The coercion is always nominal. -- INVARIANT: The cast is never refl. - -- INVARIANT: The cast is "pushed down" as far as it - -- can go. See Note [Pushing down casts] + -- INVARIANT: The Type is not a CastTy (use TransCo instead) + -- See Note [Respecting definitional equality] (EQ2) and (EQ3) | CoercionTy Coercion -- ^ Injection of a Coercion into a type @@ -333,19 +354,12 @@ kinds or types. This kind instantiation only happens in TyConApp currently. -Note [Pushing down casts] -~~~~~~~~~~~~~~~~~~~~~~~~~ -Suppose we have (a :: k1 -> *), (b :: k1), and (co :: * ~ q). -The type (a b |> co) is `eqType` to ((a |> co') b), where -co' = (->) <k1> co. Thus, to make this visible to functions -that inspect types, we always push down coercions, preferring -the second form. Note that this also applies to TyConApps! - Note [Non-trivial definitional equality] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Is Int |> <*> the same as Int? YES! In order to reduce headaches, -we decide that any reflexive casts in types are just ignored. More -generally, the `eqType` function, which defines Core's type equality +we decide that any reflexive casts in types are just ignored. +(Indeed they must be. See Note [Respecting definitional equality].) +More generally, the `eqType` function, which defines Core's type equality relation, ignores casts and coercion arguments, as long as the two types have the same kind. This allows us to be a little sloppier in keeping track of coercions, which is a good thing. It also means @@ -357,11 +371,11 @@ appropriate for the implementation of eqType? Anything smaller than ~ and homogeneous is an appropriate definition for equality. The type safety of FC depends only on ~. Let's say η : τ ~ σ. Any expression of type τ can be transmuted to one of type σ at any point by -casting. The same is true of types of type τ. So in some sense, τ and σ are -interchangeable. +casting. The same is true of expressions of type σ. So in some sense, τ and σ +are interchangeable. But let's be more precise. If we examine the typing rules of FC (say, those in -http://www.cis.upenn.edu/~eir/papers/2015/equalities/equalities-extended.pdf) +https://cs.brynmawr.edu/~rae/papers/2015/equalities/equalities.pdf) there are several places where the same metavariable is used in two different premises to a rule. (For example, see Ty_App.) There is an implicit equality check here. What definition of equality should we use? By convention, we use @@ -378,6 +392,9 @@ The effect of this all is that eqType, the implementation of the implicit equality check, can use any homogeneous relation that is smaller than ~, as those rules must also be admissible. +A more drawn out argument around all of this is presented in Section 7.2 of +Richard E's thesis (http://cs.brynmawr.edu/~rae/papers/2016/thesis/eisenberg-thesis.pdf). + What would go wrong if we insisted on the casts matching? See the beginning of Section 8 in the unpublished paper above. Theoretically, nothing at all goes wrong. But in practical terms, getting the coercions right proved to be @@ -398,48 +415,145 @@ constructors and destructors in Type respect whatever relation is chosen. Another helpful principle with eqType is this: - ** If (t1 eqType t2) then I can replace t1 by t2 anywhere. ** + (EQ) If (t1 `eqType` t2) then I can replace t1 by t2 anywhere. This principle also tells us that eqType must relate only types with the same kinds. + +Note [Respecting definitional equality] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note [Non-trivial definitional equality] introduces the property (EQ). +How is this upheld? + +Any function that pattern matches on all the constructors will have to +consider the possibility of CastTy. Presumably, those functions will handle +CastTy appropriately and we'll be OK. + +More dangerous are the splitXXX functions. Let's focus on splitTyConApp. +We don't want it to fail on (T a b c |> co). Happily, if we have + (T a b c |> co) `eqType` (T d e f) +then co must be reflexive. Why? eqType checks that the kinds are equal, as +well as checking that (a `eqType` d), (b `eqType` e), and (c `eqType` f). +By the kind check, we know that (T a b c |> co) and (T d e f) have the same +kind. So the only way that co could be non-reflexive is for (T a b c) to have +a different kind than (T d e f). But because T's kind is closed (all tycon kinds +are closed), the only way for this to happen is that one of the arguments has +to differ, leading to a contradiction. Thus, co is reflexive. + +Accordingly, by eliminating reflexive casts, splitTyConApp need not worry +about outermost casts to uphold (EQ). Eliminating reflexive casts is done +in mkCastTy. + +Unforunately, that's not the end of the story. Consider comparing + (T a b c) =? (T a b |> (co -> <Type>)) (c |> co) +These two types have the same kind (Type), but the left type is a TyConApp +while the right type is not. To handle this case, we say that the right-hand +type is ill-formed, requiring an AppTy never to have a casted TyConApp +on its left. It is easy enough to pull around the coercions to maintain +this invariant, as done in Type.mkAppTy. In the example above, trying to +form the right-hand type will instead yield (T a b (c |> co |> sym co) |> <Type>). +Both the casts there are reflexive and will be dropped. Huzzah. + +This idea of pulling coercions to the right works for splitAppTy as well. + +However, there is one hiccup: it's possible that a coercion doesn't relate two +Pi-types. For example, if we have @type family Fun a b where Fun a b = a -> b@, +then we might have (T :: Fun Type Type) and (T |> axFun) Int. That axFun can't +be pulled to the right. But we don't need to pull it: (T |> axFun) Int is not +`eqType` to any proper TyConApp -- thus, leaving it where it is doesn't violate +our (EQ) property. + +Lastly, in order to detect reflexive casts reliably, we must make sure not +to have nested casts: we update (t |> co1 |> co2) to (t |> (co1 `TransCo` co2)). + +In sum, in order to uphold (EQ), we need the following three invariants: + + (EQ1) No decomposable CastTy to the left of an AppTy, where a decomposable + cast is one that relates either a FunTy to a FunTy or a + ForAllTy to a ForAllTy. + (EQ2) No reflexive casts in CastTy. + (EQ3) No nested CastTys. + (EQ4) No CastTy over (ForAllTy (Bndr tyvar vis) body). + See Note [Weird typing rule for ForAllTy] in Type. + +These invariants are all documented above, in the declaration for Type. + +Note [Unused coercion variable in ForAllTy] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Suppose we have + \(co:t1 ~ t2). e + +What type should we give to this expression? + (1) forall (co:t1 ~ t2) -> t + (2) (t1 ~ t2) -> t + +If co is used in t, (1) should be the right choice. +if co is not used in t, we would like to have (1) and (2) equivalent. + +However, we want to keep eqType simple and don't want eqType (1) (2) to return +True in any case. + +We decide to always construct (2) if co is not used in t. + +Thus in mkTyCoForAllTy, we check whether the variable is a coercion +variable and whether it is used in the body. If so, it returns a FunTy +instead of a ForAllTy. + +There are cases we want to skip the check. For example, the check is unnecessary +when it is known from the context that the input variable is a type variable. +In those cases, we use mkForAllTy. -} +-- | A type labeled 'KnotTied' might have knot-tied tycons in it. See +-- Note [Type checking recursive type and class declarations] in +-- TcTyClsDecls +type KnotTied ty = ty + {- ********************************************************************** * * - TyBinder and ArgFlag + TyCoBinder and ArgFlag * * ********************************************************************** -} --- | A 'TyBinder' represents an argument to a function. TyBinders can be dependent --- ('Named') or nondependent ('Anon'). They may also be visible or not. --- See Note [TyBinders] -data TyBinder - = Named TyVarBinder -- A type-lambda binder - | Anon Type -- A term-lambda binder +-- | A 'TyCoBinder' represents an argument to a function. TyCoBinders can be +-- dependent ('Named') or nondependent ('Anon'). They may also be visible or +-- not. See Note [TyCoBinders] +data TyCoBinder + = Named TyCoVarBinder -- A type-lambda binder + | Anon Type -- A term-lambda binder. Type here can be CoercionTy. -- Visibility is determined by the type (Constraint vs. *) deriving Data.Data +-- | 'TyBinder' is like 'TyCoBinder', but there can only be 'TyVarBinder' +-- in the 'Named' field. +type TyBinder = TyCoBinder + -- | Remove the binder's variable from the set, if the binder has -- a variable. -delBinderVar :: VarSet -> TyVarBinder -> VarSet -delBinderVar vars (TvBndr tv _) = vars `delVarSet` tv +delBinderVar :: VarSet -> TyCoVarBinder -> VarSet +delBinderVar vars (Bndr tv _) = vars `delVarSet` tv -- | Does this binder bind an invisible argument? -isInvisibleBinder :: TyBinder -> Bool -isInvisibleBinder (Named (TvBndr _ vis)) = isInvisibleArgFlag vis -isInvisibleBinder (Anon ty) = isPredTy ty +isInvisibleBinder :: TyCoBinder -> Bool +isInvisibleBinder (Named (Bndr _ vis)) = isInvisibleArgFlag vis +isInvisibleBinder (Anon ty) = isPredTy ty -- | Does this binder bind a visible argument? -isVisibleBinder :: TyBinder -> Bool +isVisibleBinder :: TyCoBinder -> Bool isVisibleBinder = not . isInvisibleBinder +-- | If its a named binder, is the binder a tyvar? +-- Returns True for nondependent binder. +isTyBinder :: TyCoBinder -> Bool +isTyBinder (Named bnd) = isTyVarBinder bnd +isTyBinder _ = True -{- Note [TyBinders] +{- Note [TyCoBinders] ~~~~~~~~~~~~~~~~~~~ -A ForAllTy contains a TyVarBinder. But a type can be decomposed -to a telescope consisting of a [TyBinder] +A ForAllTy contains a TyCoVarBinder. But a type can be decomposed +to a telescope consisting of a [TyCoBinder] -A TyBinder represents the type of binders -- that is, the type of an +A TyCoBinder represents the type of binders -- that is, the type of an argument to a Pi-type. GHC Core currently supports two different Pi-types: @@ -457,36 +571,47 @@ words, if `x` is either a function or a polytype, `x arg` makes sense (for an appropriate `arg`). -Note [TyBinders and ArgFlags] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A ForAllTy contains a TyVarBinder. Each TyVarBinder is equipped -with a ArgFlag, which says whether or not arguments for this -binder should be visible (explicit) in source Haskell. - ------------------------------------------------------------------------ - Occurrences look like this - TyBinder GHC displays type as in Haskell souce code ------------------------------------------------------------------------ -In the type of a term - Anon: f :: type -> type Arg required: f x - Named Inferred: f :: forall {a}. type Arg not allowed: f - Named Specified: f :: forall a. type Arg optional: f or f @Int - Named Required: Illegal: See Note [No Required TyBinder in terms] - -In the kind of a type - Anon: T :: kind -> kind Required: T * - Named Inferred: T :: forall {k}. kind Arg not allowed: T - Named Specified: T :: forall k. kind Arg not allowed[1]: T - Named Required: T :: forall k -> kind Required: T * ------------------------------------------------------------------------- +Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* A ForAllTy (used for both types and kinds) contains a TyCoVarBinder. + Each TyCoVarBinder + Bndr a tvis + is equipped with tvis::ArgFlag, which says whether or not arguments + for this binder should be visible (explicit) in source Haskell. + +* A TyCon contains a list of TyConBinders. Each TyConBinder + Bndr a cvis + is equipped with cvis::TyConBndrVis, which says whether or not type + and kind arguments for this TyCon should be visible (explicit) in + source Haskell. + +This table summarises the visibility rules: +--------------------------------------------------------------------------------------- +| Occurrences look like this +| GHC displays type as in Haskell source code +|-------------------------------------------------------------------------------------- +| Bndr a tvis :: TyCoVarBinder, in the binder of ForAllTy for a term +| tvis :: ArgFlag +| tvis = Inferred: f :: forall {a}. type Arg not allowed: f + f :: forall {co}. type Arg not allowed: f +| tvis = Specified: f :: forall a. type Arg optional: f or f @Int +| tvis = Required: T :: forall k -> type Arg required: T * +| This last form is illegal in terms: See Note [No Required TyCoBinder in terms] +| +| Bndr k cvis :: TyConBinder, in the TyConBinders of a TyCon +| cvis :: TyConBndrVis +| cvis = AnonTCB: T :: kind -> kind Required: T * +| cvis = NamedTCB Inferred: T :: forall {k}. kind Arg not allowed: T +| T :: forall {co}. kind Arg not allowed: T +| cvis = NamedTCB Specified: T :: forall k. kind Arg not allowed[1]: T +| cvis = NamedTCB Required: T :: forall k -> kind Required: T * +--------------------------------------------------------------------------------------- [1] In types, in the Specified case, it would make sense to allow optional kind applications, thus (T @*), but we have not yet implemented that ----- Examples of where the different visibilities come from ----- - -In term declarations: +---- In term declarations ---- * Inferred. Function defn, with no signature: f1 x = x We infer f1 :: forall {a}. a -> a, with 'a' Inferred @@ -495,12 +620,12 @@ In term declarations: * Specified. Function defn, with signature (implicit forall): f2 :: a -> a; f2 x = x - So f2 gets the type f2 :: forall a. a->a, with 'a' Specified + So f2 gets the type f2 :: forall a. a -> a, with 'a' Specified even though 'a' is not bound in the source code by an explicit forall * Specified. Function defn, with signature (explicit forall): f3 :: forall a. a -> a; f3 x = x - So f3 gets the type f3 :: forall a. a->a, with 'a' Specified + So f3 gets the type f3 :: forall a. a -> a, with 'a' Specified * Inferred/Specified. Function signature with inferred kind polymorphism. f4 :: a b -> Int @@ -517,14 +642,14 @@ In term declarations: Inferred - from inferred types (e.g. no pattern type signature) - or from inferred kind polymorphism -In type declarations: +---- In type declarations ---- * Inferred (k) data T1 a b = MkT1 (a b) Here T1's kind is T1 :: forall {k:*}. (k->*) -> k -> * The kind variable 'k' is Inferred, since it is not mentioned - Note that 'a' and 'b' correspond to /Anon/ TyBinders in T1's kind, + Note that 'a' and 'b' correspond to /Anon/ TyCoBinders in T1's kind, and Anon binders don't have a visibility flag. (Or you could think of Anon having an implicit Required flag.) @@ -546,6 +671,19 @@ In type declarations: So 'k' is Specified, because it appears explicitly, but 'k1' is Inferred, because it does not +Generally, in the list of TyConBinders for a TyCon, + +* Inferred arguments always come first +* Specified, Anon and Required can be mixed + +e.g. + data Foo (a :: Type) :: forall b. (a -> b -> Type) -> Type where ... + +Here Foo's TyConBinders are + [Required 'a', Specified 'b', Anon] +and its kind prints as + Foo :: forall a -> forall b. (a -> b -> Type) -> Type + ---- Printing ----- We print forall types with enough syntax to tell you their visibility @@ -571,14 +709,14 @@ In type declarations: * Inferred variables correspond to "generalized" variables from the Visible Type Applications paper (ESOP'16). -Note [No Required TyBinder in terms] +Note [No Required TyCoBinder in terms] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We don't allow Required foralls for term variables, including pattern synonyms and data constructors. Why? Because then an application would need a /compulsory/ type argument (possibly without an "@"?), thus (f Int); and we don't have concrete syntax for that. -We could change this decision, but Required, Named TyBinders are rare +We could change this decision, but Required, Named TyCoBinders are rare anyway. (Most are Anons.) -} @@ -639,14 +777,23 @@ These functions are here so that they can be used by TysPrim, which in turn is imported by Type -} --- named with "Only" to prevent naive use of mkTyVarTy mkTyVarTy :: TyVar -> Type mkTyVarTy v = ASSERT2( isTyVar v, ppr v <+> dcolon <+> ppr (tyVarKind v) ) - TyVarTy v + TyVarTy v mkTyVarTys :: [TyVar] -> [Type] mkTyVarTys = map mkTyVarTy -- a common use of mkTyVarTy +mkTyCoVarTy :: TyCoVar -> Type +mkTyCoVarTy v + | isTyVar v + = TyVarTy v + | otherwise + = CoercionTy (CoVarCo v) + +mkTyCoVarTys :: [TyCoVar] -> [Type] +mkTyCoVarTys = map mkTyCoVarTy + infixr 3 `mkFunTy` -- Associates to the right -- | Make an arrow type mkFunTy :: Type -> Type -> Type @@ -656,18 +803,41 @@ mkFunTy arg res = FunTy arg res mkFunTys :: [Type] -> Type -> Type mkFunTys tys ty = foldr mkFunTy ty tys -mkForAllTy :: TyVar -> ArgFlag -> Type -> Type -mkForAllTy tv vis ty = ForAllTy (TvBndr tv vis) ty +-- | If tv is a coercion variable and it is not used in the body, returns +-- a FunTy, otherwise makes a forall type. +-- See Note [Unused coercion variable in ForAllTy] +mkTyCoForAllTy :: TyCoVar -> ArgFlag -> Type -> Type +mkTyCoForAllTy tv vis ty + | isCoVar tv + , not (tv `elemVarSet` tyCoVarsOfType ty) + = ASSERT( vis == Inferred ) + mkFunTy (varType tv) ty + | otherwise + = ForAllTy (Bndr tv vis) ty --- | Wraps foralls over the type using the provided 'TyVar's from left to right -mkForAllTys :: [TyVarBinder] -> Type -> Type +-- | Like 'mkTyCoForAllTy', but does not check the occurrence of the binder +-- See Note [Unused coercion variable in ForAllTy] +mkForAllTy :: TyCoVar -> ArgFlag -> Type -> Type +mkForAllTy tv vis ty = ForAllTy (Bndr tv vis) ty + +-- | Wraps foralls over the type using the provided 'TyCoVar's from left to right +mkForAllTys :: [TyCoVarBinder] -> Type -> Type mkForAllTys tyvars ty = foldr ForAllTy ty tyvars -mkPiTy :: TyBinder -> Type -> Type -mkPiTy (Anon ty1) ty2 = FunTy ty1 ty2 -mkPiTy (Named tvb) ty = ForAllTy tvb ty +mkTyCoPiTy :: TyCoBinder -> Type -> Type +mkTyCoPiTy (Anon ty1) ty2 = FunTy ty1 ty2 +mkTyCoPiTy (Named (Bndr tv vis)) ty = mkTyCoForAllTy tv vis ty + +-- | Like 'mkTyCoPiTy', but does not check the occurrence of the binder +mkPiTy:: TyCoBinder -> Type -> Type +mkPiTy (Anon ty1) ty2 = FunTy ty1 ty2 +mkPiTy (Named (Bndr tv vis)) ty = mkForAllTy tv vis ty -mkPiTys :: [TyBinder] -> Type -> Type +mkTyCoPiTys :: [TyCoBinder] -> Type -> Type +mkTyCoPiTys tbs ty = foldr mkTyCoPiTy ty tbs + +-- | Like 'mkTyCoPiTys', but does not check the occurrence of the binder +mkPiTys :: [TyCoBinder] -> Type -> Type mkPiTys tbs ty = foldr mkPiTy ty tbs -- | Does this type classify a core (unlifted) Coercion? @@ -689,22 +859,28 @@ mkTyConTy tycon = TyConApp tycon [] Some basic functions, put here to break loops eg with the pretty printer -} -is_TYPE :: ( Type -- the single argument to TYPE; not a synonym - -> Bool ) -- what to return - -> Kind -> Bool -is_TYPE f ki | Just ki' <- coreView ki = is_TYPE f ki' -is_TYPE f (TyConApp tc [arg]) +-- | If a type is @'TYPE' r@ for some @r@, run the predicate argument on @r@. +-- Otherwise, return 'False'. +-- +-- This function does not distinguish between 'Constraint' and 'Type'. For a +-- version which does distinguish between the two, see 'tcIsTYPE'. +isTYPE :: ( Type -- the single argument to TYPE; not a synonym + -> Bool ) -- what to return + -> Kind -> Bool +isTYPE f ki | Just ki' <- coreView ki = isTYPE f ki' +isTYPE f (TyConApp tc [arg]) | tc `hasKey` tYPETyConKey = go arg where go ty | Just ty' <- coreView ty = go ty' go ty = f ty -is_TYPE _ _ = False +isTYPE _ _ = False --- | This version considers Constraint to be distinct from *. Returns True --- if the argument is equivalent to Type and False otherwise. +-- | This version considers Constraint to be the same as *. Returns True +-- if the argument is equivalent to Type/Constraint and False otherwise. +-- See Note [Kind Constraint and kind Type] isLiftedTypeKind :: Kind -> Bool -isLiftedTypeKind = is_TYPE is_lifted +isLiftedTypeKind = isTYPE is_lifted where is_lifted (TyConApp lifted_rep []) = lifted_rep `hasKey` liftedRepDataConKey is_lifted _ = False @@ -713,9 +889,9 @@ isLiftedTypeKind = is_TYPE is_lifted -- Note that this returns False for levity-polymorphic kinds, which may -- be specialized to a kind that classifies unlifted types. isUnliftedTypeKind :: Kind -> Bool -isUnliftedTypeKind = is_TYPE is_unlifted +isUnliftedTypeKind = isTYPE is_unlifted where - is_unlifted (TyConApp rr _args) = not (rr `hasKey` liftedRepDataConKey) + is_unlifted (TyConApp rr _args) = elem (getUnique rr) unliftedRepDataConKeys is_unlifted _ = False -- | Is this the type 'RuntimeRep'? @@ -724,23 +900,10 @@ isRuntimeRepTy ty | Just ty' <- coreView ty = isRuntimeRepTy ty' isRuntimeRepTy (TyConApp tc []) = tc `hasKey` runtimeRepTyConKey isRuntimeRepTy _ = False --- | Is this a type of kind RuntimeRep? (e.g. LiftedRep) -isRuntimeRepKindedTy :: Type -> Bool -isRuntimeRepKindedTy = isRuntimeRepTy . typeKind - -- | Is a tyvar of type 'RuntimeRep'? isRuntimeRepVar :: TyVar -> Bool isRuntimeRepVar = isRuntimeRepTy . tyVarKind --- | Drops prefix of RuntimeRep constructors in 'TyConApp's. Useful for e.g. --- dropping 'LiftedRep arguments of unboxed tuple TyCon applications: --- --- dropRuntimeRepArgs [ 'LiftedRep, 'IntRep --- , String, Int# ] == [String, Int#] --- -dropRuntimeRepArgs :: [Type] -> [Type] -dropRuntimeRepArgs = dropWhile isRuntimeRepKindedTy - {- %************************************************************************ %* * @@ -764,8 +927,8 @@ data Coercion -- - _ stands for a parameter that is not a Role or Coercion. -- These ones mirror the shape of types - = -- Refl :: "e" -> _ -> e - Refl Role Type -- See Note [Refl invariant] + = -- Refl :: _ -> N + Refl Type -- See Note [Refl invariant] -- Invariant: applications of (Refl T) to a bunch of identity coercions -- always show up as Refl. -- For example (Refl T) (Refl a) (Refl b) shows up as (Refl (T a b)). @@ -776,7 +939,13 @@ data Coercion -- ConAppCo coercions (like all coercions other than Refl) -- are NEVER the identity. - -- Use (Refl Representational _), not (SubCo (Refl Nominal _)) + -- Use (GRefl Representational ty MRefl), not (SubCo (Refl ty)) + + -- GRefl :: "e" -> _ -> Maybe N -> e + -- See Note [Generalized reflexive coercion] + | GRefl Role Type MCoercionN -- See Note [Refl invariant] + -- Use (Refl ty), not (GRefl Nominal ty MRefl) + -- Use (GRefl Representational _ _), not (SubCo (GRefl Nominal _ _)) -- These ones simply lift the correspondingly-named -- Type constructors into Coercions @@ -792,7 +961,7 @@ data Coercion -- AppCo :: e -> N -> e -- See Note [Forall coercions] - | ForAllCo TyVar KindCoercion Coercion + | ForAllCo TyCoVar KindCoercion Coercion -- ForAllCo :: _ -> N -> e -> e | FunCo Role Coercion Coercion -- lift FunTy @@ -810,20 +979,25 @@ data Coercion -- any left over, we use AppCo. -- See [Coercion axioms applied to coercions] + | AxiomRuleCo CoAxiomRule [Coercion] + -- AxiomRuleCo is very like AxiomInstCo, but for a CoAxiomRule + -- The number coercions should match exactly the expectations + -- of the CoAxiomRule (i.e., the rule is fully saturated). + | UnivCo UnivCoProvenance Role Type Type -- :: _ -> "e" -> _ -> _ -> e | SymCo Coercion -- :: e -> e | TransCo Coercion Coercion -- :: e -> e -> e - -- The number coercions should match exactly the expectations - -- of the CoAxiomRule (i.e., the rule is fully saturated). - | AxiomRuleCo CoAxiomRule [Coercion] - - | NthCo Int Coercion -- Zero-indexed; decomposes (T t0 ... tn) - -- :: _ -> e -> ?? (inverse of TyConAppCo, see Note [TyConAppCo roles]) + | NthCo Role Int Coercion -- Zero-indexed; decomposes (T t0 ... tn) + -- :: "e" -> _ -> e0 -> e (inverse of TyConAppCo, see Note [TyConAppCo roles]) -- Using NthCo on a ForAllCo gives an N coercion always -- See Note [NthCo and newtypes] + -- + -- Invariant: (NthCo r i co), it is always the case that r = role of (Nth i co) + -- That is: the role of the entire coercion is redundantly cached here. + -- See Note [NthCo Cached Roles] | LRCo LeftOrRight CoercionN -- Decomposes (t_left t_right) -- :: _ -> N -> N @@ -831,11 +1005,6 @@ data Coercion -- :: e -> N -> e -- See Note [InstCo roles] - -- Coherence applies a coercion to the left-hand type of another coercion - -- See Note [Coherence] - | CoherenceCo Coercion KindCoercion - -- :: e -> N -> e - -- Extract a kind coercion from a (heterogeneous) type coercion -- NB: all kind coercions are Nominal | KindCo Coercion @@ -844,6 +1013,8 @@ data Coercion | SubCo CoercionN -- Turns a ~N into a ~R -- :: N -> R + | HoleCo CoercionHole -- ^ See Note [Coercion holes] + -- Only present during typechecking deriving Data.Data type CoercionN = Coercion -- always nominal @@ -851,13 +1022,28 @@ type CoercionR = Coercion -- always representational type CoercionP = Coercion -- always phantom type KindCoercion = CoercionN -- always nominal +-- | A semantically more meaningful type to represent what may or may not be a +-- useful 'Coercion'. +data MCoercion + = MRefl + -- A trivial Reflexivity coercion + | MCo Coercion + -- Other coercions + deriving Data.Data +type MCoercionR = MCoercion +type MCoercionN = MCoercion + +instance Outputable MCoercion where + ppr MRefl = text "MRefl" + ppr (MCo co) = text "MCo" <+> ppr co + {- Note [Refl invariant] ~~~~~~~~~~~~~~~~~~~~~ Invariant 1: Coercions have the following invariant - Refl is always lifted as far as possible. + Refl (similar for GRefl r ty MRefl) is always lifted as far as possible. You might think that a consequencs is: Every identity coercions has Refl at the root @@ -868,6 +1054,42 @@ But that's not quite true because of coercion variables. Consider etc. So the consequence is only true of coercions that have no coercion variables. +Note [Generalized reflexive coercion] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +GRefl is a generalized reflexive coercion (see Trac #15192). It wraps a kind +coercion, which might be reflexive (MRefl) or any coercion (MCo co). The typing +rules for GRefl: + + ty : k1 + ------------------------------------ + GRefl r ty MRefl: ty ~r ty + + ty : k1 co :: k1 ~ k2 + ------------------------------------ + GRefl r ty (MCo co) : ty ~r ty |> co + +Consider we have + + g1 :: s ~r t + s :: k1 + g2 :: k1 ~ k2 + +and we want to construct a coercions co which has type + + (s |> g2) ~r t + +We can define + + co = Sym (GRefl r s g2) ; g1 + +It is easy to see that + + Refl == GRefl Nominal ty MRefl :: ty ~n ty + +A nominal reflexive coercion is quite common, so we keep the special form Refl to +save allocation. + Note [Coercion axioms applied to coercions] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The reason coercion axioms can be applied to coercions and not just @@ -936,9 +1158,10 @@ The typing rule is: ForAllCo tv1 kind_co co : all tv1:k1. t1 ~ all tv1:k2. (t2[tv1 |-> tv1 |> sym kind_co]) -First, the TyVar stored in a ForAllCo is really an optimisation: this field +First, the TyCoVar stored in a ForAllCo is really an optimisation: this field should be a Name, as its kind is redundant. Thinking of the field as a Name is helpful in understanding what a ForAllCo means. +The kind of TyCoVar always matches the left-hand kind of the coercion. The idea is that kind_co gives the two kinds of the tyvar. See how, in the conclusion, tv1 is assigned kind k1 on the left but kind k2 on the right. @@ -959,19 +1182,6 @@ add Names to, e.g., VarSets, and there generally is just an impedance mismatch in a bunch of places. So we use tv1. When we need tv2, we can use setTyVarKind. -Note [Coherence] -~~~~~~~~~~~~~~~~ -The Coherence typing rule is thus: - - g1 : s ~ t s : k1 g2 : k1 ~ k2 - ------------------------------------ - CoherenceCo g1 g2 : (s |> g2) ~ t - -While this looks (and is) unsymmetric, a combination of other coercion -combinators can make the symmetric version. - -For role information, see Note [Roles and kind coercions]. - Note [Predicate coercions] ~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose we have @@ -1131,7 +1341,7 @@ We can then build for any `a` and `b`. Because of the role annotation on N, if we use NthCo, we'll get out a representational coercion. That is: - NthCo 0 co :: forall a b. a ~R b + NthCo r 0 co :: forall a b. a ~R b Yikes! Clearly, this is terrible. The solution is simple: forbid NthCo to be used on newtypes if the internal coercion is representational. @@ -1140,6 +1350,23 @@ This is not just some corner case discovered by a segfault somewhere; it was discovered in the proof of soundness of roles and described in the "Safe Coercions" paper (ICFP '14). +Note [NthCo Cached Roles] +~~~~~~~~~~~~~~~~~~~~~~~~~ +Why do we cache the role of NthCo in the NthCo constructor? +Because computing role(Nth i co) involves figuring out that + + co :: T tys1 ~ T tys2 + +using coercionKind, and finding (coercionRole co), and then looking +at the tyConRoles of T. Avoiding bad asymptotic behaviour here means +we have to compute the kind and role of a coercion simultaneously, +which makes the code complicated and inefficient. + +This only happens for NthCo. Caching the role solves the problem, and +allows coercionKind and coercionRole to be simple. + +See Trac #11735 + Note [InstCo roles] ~~~~~~~~~~~~~~~~~~~ Here is (essentially) the typing rule for InstCo: @@ -1197,7 +1424,6 @@ data UnivCoProvenance | PluginProv String -- ^ From a plugin, which asserts that this coercion -- is sound. The string is for the use of the plugin. - | HoleProv CoercionHole -- ^ See Note [Coercion holes] deriving Data.Data instance Outputable UnivCoProvenance where @@ -1205,14 +1431,21 @@ instance Outputable UnivCoProvenance where ppr (PhantomProv _) = text "(phantom)" ppr (ProofIrrelProv _) = text "(proof irrel.)" ppr (PluginProv str) = parens (text "plugin" <+> brackets (text str)) - ppr (HoleProv hole) = parens (text "hole" <> ppr hole) -- | A coercion to be filled in by the type-checker. See Note [Coercion holes] data CoercionHole - = CoercionHole { chUnique :: Unique -- ^ used only for debugging - , chCoercion :: IORef (Maybe Coercion) + = CoercionHole { ch_co_var :: CoVar + -- See Note [CoercionHoles and coercion free variables] + + , ch_ref :: IORef (Maybe Coercion) } +coHoleCoVar :: CoercionHole -> CoVar +coHoleCoVar = ch_co_var + +setCoHoleCoVar :: CoercionHole -> CoVar -> CoercionHole +setCoHoleCoVar h cv = h { ch_co_var = cv } + instance Data.Data CoercionHole where -- don't traverse? toConstr _ = abstractConstr "CoercionHole" @@ -1220,7 +1453,7 @@ instance Data.Data CoercionHole where dataTypeOf _ = mkNoRepType "CoercionHole" instance Outputable CoercionHole where - ppr (CoercionHole u _) = braces (ppr u) + ppr (CoercionHole { ch_co_var = cv }) = braces (ppr cv) {- Note [Phantom coercions] @@ -1247,7 +1480,7 @@ During typechecking, constraint solving for type classes works by For equality constraints we use a different strategy. See Note [The equality types story] in TysPrim for background on equality constraints. - - For boxed equality constraints, (t1 ~N t2) and (t1 ~R t2), it's just + - For /boxed/ equality constraints, (t1 ~N t2) and (t1 ~R t2), it's just like type classes above. (Indeed, boxed equality constraints *are* classes.) - But for /unboxed/ equality constraints (t1 ~R# t2) and (t1 ~N# t2) we use a different plan @@ -1256,40 +1489,61 @@ For unboxed equalities: - Generate a CoercionHole, a mutable variable just like a unification variable - Wrap the CoercionHole in a Wanted constraint; see TcRnTypes.TcEvDest - - Use the CoercionHole in a Coercion, via HoleProv + - Use the CoercionHole in a Coercion, via HoleCo - Solve the constraint later - When solved, fill in the CoercionHole by side effect, instead of doing the let-binding thing The main reason for all this is that there may be no good place to let-bind the evidence for unboxed equalities: - - We emit constraints for kind coercions, to be used - to cast a type's kind. These coercions then must be used in types. Because - they might appear in a top-level type, there is no place to bind these - (unlifted) coercions in the usual way. - - A coercion for (forall a. t1) ~ forall a. t2) will look like + - We emit constraints for kind coercions, to be used to cast a + type's kind. These coercions then must be used in types. Because + they might appear in a top-level type, there is no place to bind + these (unlifted) coercions in the usual way. + + - A coercion for (forall a. t1) ~ (forall a. t2) will look like forall a. (coercion for t1~t2) - But the coercion for (t1~t2) may mention 'a', and we don't have let-bindings - within coercions. We could add them, but coercion holes are easier. + But the coercion for (t1~t2) may mention 'a', and we don't have + let-bindings within coercions. We could add them, but coercion + holes are easier. + + - Moreover, nothing is lost from the lack of let-bindings. For + dicionaries want to achieve sharing to avoid recomoputing the + dictionary. But coercions are entirely erased, so there's little + benefit to sharing. Indeed, even if we had a let-binding, we + always inline types and coercions at every use site and drop the + binding. Other notes about HoleCo: - * INVARIANT: CoercionHole and HoleProv are used only during type checking, + * INVARIANT: CoercionHole and HoleCo are used only during type checking, and should never appear in Core. Just like unification variables; a Type can contain a TcTyVar, but only during type checking. If, one day, we use type-level information to separate out forms that can appear during type-checking vs forms that can appear in core proper, holes in Core will be ruled out. - * The Unique carried with a coercion hole is used solely for debugging. + * See Note [CoercionHoles and coercion free variables] - * Coercion holes can be compared for equality only like other coercions: - only by looking at the types coerced. + * Coercion holes can be compared for equality like other coercions: + by looking at the types coerced. + + +Note [CoercionHoles and coercion free variables] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Why does a CoercionHole contain a CoVar, as well as reference to +fill in? Because we want to treat that CoVar as a free variable of +the coercion. See Trac #14584, and Note [What prevents a +constraint from floating] in TcSimplify, item (4): + + forall k. [W] co1 :: t1 ~# t2 |> co2 + [W] co2 :: k ~# * + +Here co2 is a CoercionHole. But we /must/ know that it is free in +co1, because that's all that stops it floating outside the +implication. - * We don't use holes for other evidence because other evidence wants to - be /shared/. But coercions are entirely erased, so there's little - benefit to sharing. Note [ProofIrrelProv] ~~~~~~~~~~~~~~~~~~~~~ @@ -1304,7 +1558,7 @@ In core, we get MkG :: forall (a :: *). (a ~ Bool) -> G a Now, consider 'MkG -- that is, MkG used in a type -- and suppose we want -a proof that ('MkG co1 a1) ~ ('MkG co2 a2). This will have to be +a proof that ('MkG a1 co1) ~ ('MkG a2 co2). This will have to be TyConAppCo Nominal MkG [co3, co4] where @@ -1319,7 +1573,7 @@ Here, co3 = UnivCo (ProofIrrelProv co5) Nominal (CoercionTy co1) (CoercionTy co2) where co5 :: (a1 ~ Bool) ~ (a2 ~ Bool) - co5 = TyConAppCo Nominal (~) [<*>, <*>, co4, <Bool>] + co5 = TyConAppCo Nominal (~#) [<*>, <*>, co4, <Bool>] %************************************************************************ @@ -1386,10 +1640,10 @@ tyCoFVsOfType (ForAllTy bndr ty) a b c = tyCoFVsBndr bndr (tyCoFVsOfType ty) a tyCoFVsOfType (CastTy ty co) a b c = (tyCoFVsOfType ty `unionFV` tyCoFVsOfCo co) a b c tyCoFVsOfType (CoercionTy co) a b c = tyCoFVsOfCo co a b c -tyCoFVsBndr :: TyVarBinder -> FV -> FV +tyCoFVsBndr :: TyCoVarBinder -> FV -> FV -- Free vars of (forall b. <thing with fvs>) -tyCoFVsBndr (TvBndr tv _) fvs = (delFV tv fvs) - `unionFV` tyCoFVsOfType (tyVarKind tv) +tyCoFVsBndr (Bndr tv _) fvs = (delFV tv fvs) + `unionFV` tyCoFVsOfType (varType tv) -- | Returns free variables of types, including kind variables as -- a non-deterministic set. For type synonyms it does /not/ expand the @@ -1439,10 +1693,17 @@ tyCoVarsOfCoList :: Coercion -> [TyCoVar] -- See Note [Free variables of types] tyCoVarsOfCoList co = fvVarList $ tyCoFVsOfCo co +tyCoFVsOfMCo :: MCoercion -> FV +tyCoFVsOfMCo MRefl = emptyFV +tyCoFVsOfMCo (MCo co) = tyCoFVsOfCo co + tyCoFVsOfCo :: Coercion -> FV -- Extracts type and coercion variables from a coercion -- See Note [Free variables of types] -tyCoFVsOfCo (Refl _ ty) fv_cand in_scope acc = tyCoFVsOfType ty fv_cand in_scope acc +tyCoFVsOfCo (Refl ty) fv_cand in_scope acc + = tyCoFVsOfType ty fv_cand in_scope acc +tyCoFVsOfCo (GRefl _ ty mco) fv_cand in_scope acc + = (tyCoFVsOfType ty `unionFV` tyCoFVsOfMCo mco) fv_cand in_scope acc tyCoFVsOfCo (TyConAppCo _ _ cos) fv_cand in_scope acc = tyCoFVsOfCos cos fv_cand in_scope acc tyCoFVsOfCo (AppCo co arg) fv_cand in_scope acc = (tyCoFVsOfCo co `unionFV` tyCoFVsOfCo arg) fv_cand in_scope acc @@ -1451,21 +1712,27 @@ tyCoFVsOfCo (ForAllCo tv kind_co co) fv_cand in_scope acc tyCoFVsOfCo (FunCo _ co1 co2) fv_cand in_scope acc = (tyCoFVsOfCo co1 `unionFV` tyCoFVsOfCo co2) fv_cand in_scope acc tyCoFVsOfCo (CoVarCo v) fv_cand in_scope acc - = (unitFV v `unionFV` tyCoFVsOfType (varType v)) fv_cand in_scope acc + = tyCoFVsOfCoVar v fv_cand in_scope acc +tyCoFVsOfCo (HoleCo h) fv_cand in_scope acc + = tyCoFVsOfCoVar (coHoleCoVar h) fv_cand in_scope acc + -- See Note [CoercionHoles and coercion free variables] tyCoFVsOfCo (AxiomInstCo _ _ cos) fv_cand in_scope acc = tyCoFVsOfCos cos fv_cand in_scope acc tyCoFVsOfCo (UnivCo p _ t1 t2) fv_cand in_scope acc = (tyCoFVsOfProv p `unionFV` tyCoFVsOfType t1 - `unionFV` tyCoFVsOfType t2) fv_cand in_scope acc + `unionFV` tyCoFVsOfType t2) fv_cand in_scope acc tyCoFVsOfCo (SymCo co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfCo (TransCo co1 co2) fv_cand in_scope acc = (tyCoFVsOfCo co1 `unionFV` tyCoFVsOfCo co2) fv_cand in_scope acc -tyCoFVsOfCo (NthCo _ co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc +tyCoFVsOfCo (NthCo _ _ co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfCo (LRCo _ co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfCo (InstCo co arg) fv_cand in_scope acc = (tyCoFVsOfCo co `unionFV` tyCoFVsOfCo arg) fv_cand in_scope acc -tyCoFVsOfCo (CoherenceCo c1 c2) fv_cand in_scope acc = (tyCoFVsOfCo c1 `unionFV` tyCoFVsOfCo c2) fv_cand in_scope acc tyCoFVsOfCo (KindCo co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfCo (SubCo co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfCo (AxiomRuleCo _ cs) fv_cand in_scope acc = tyCoFVsOfCos cs fv_cand in_scope acc +tyCoFVsOfCoVar :: CoVar -> FV +tyCoFVsOfCoVar v fv_cand in_scope acc + = (unitFV v `unionFV` tyCoFVsOfType (varType v)) fv_cand in_scope acc + tyCoVarsOfProv :: UnivCoProvenance -> TyCoVarSet tyCoVarsOfProv prov = fvVarSet $ tyCoFVsOfProv prov @@ -1474,7 +1741,6 @@ tyCoFVsOfProv UnsafeCoerceProv fv_cand in_scope acc = emptyFV fv_cand in_scop tyCoFVsOfProv (PhantomProv co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfProv (ProofIrrelProv co) fv_cand in_scope acc = tyCoFVsOfCo co fv_cand in_scope acc tyCoFVsOfProv (PluginProv _) fv_cand in_scope acc = emptyFV fv_cand in_scope acc -tyCoFVsOfProv (HoleProv _) fv_cand in_scope acc = emptyFV fv_cand in_scope acc tyCoVarsOfCos :: [Coercion] -> TyCoVarSet tyCoVarsOfCos cos = fvVarSet $ tyCoFVsOfCos cos @@ -1494,42 +1760,50 @@ coVarsOfType (TyConApp _ tys) = coVarsOfTypes tys coVarsOfType (LitTy {}) = emptyVarSet coVarsOfType (AppTy fun arg) = coVarsOfType fun `unionVarSet` coVarsOfType arg coVarsOfType (FunTy arg res) = coVarsOfType arg `unionVarSet` coVarsOfType res -coVarsOfType (ForAllTy (TvBndr tv _) ty) +coVarsOfType (ForAllTy (Bndr tv _) ty) = (coVarsOfType ty `delVarSet` tv) - `unionVarSet` coVarsOfType (tyVarKind tv) + `unionVarSet` coVarsOfType (varType tv) coVarsOfType (CastTy ty co) = coVarsOfType ty `unionVarSet` coVarsOfCo co coVarsOfType (CoercionTy co) = coVarsOfCo co coVarsOfTypes :: [Type] -> TyCoVarSet coVarsOfTypes tys = mapUnionVarSet coVarsOfType tys +coVarsOfMCo :: MCoercion -> CoVarSet +coVarsOfMCo MRefl = emptyVarSet +coVarsOfMCo (MCo co) = coVarsOfCo co + coVarsOfCo :: Coercion -> CoVarSet -- Extract *coercion* variables only. Tiresome to repeat the code, but easy. -coVarsOfCo (Refl _ ty) = coVarsOfType ty +coVarsOfCo (Refl ty) = coVarsOfType ty +coVarsOfCo (GRefl _ ty co) = coVarsOfType ty `unionVarSet` coVarsOfMCo co coVarsOfCo (TyConAppCo _ _ args) = coVarsOfCos args coVarsOfCo (AppCo co arg) = coVarsOfCo co `unionVarSet` coVarsOfCo arg coVarsOfCo (ForAllCo tv kind_co co) = coVarsOfCo co `delVarSet` tv `unionVarSet` coVarsOfCo kind_co -coVarsOfCo (FunCo _ co1 co2) = coVarsOfCo co1 `unionVarSet` coVarsOfCo co2 -coVarsOfCo (CoVarCo v) = unitVarSet v `unionVarSet` coVarsOfType (varType v) -coVarsOfCo (AxiomInstCo _ _ args) = coVarsOfCos args -coVarsOfCo (UnivCo p _ t1 t2) = coVarsOfProv p `unionVarSet` coVarsOfTypes [t1, t2] -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 arg) = coVarsOfCo co `unionVarSet` coVarsOfCo arg -coVarsOfCo (CoherenceCo c1 c2) = coVarsOfCos [c1, c2] -coVarsOfCo (KindCo co) = coVarsOfCo co -coVarsOfCo (SubCo co) = coVarsOfCo co -coVarsOfCo (AxiomRuleCo _ cs) = coVarsOfCos cs +coVarsOfCo (FunCo _ co1 co2) = coVarsOfCo co1 `unionVarSet` coVarsOfCo co2 +coVarsOfCo (CoVarCo v) = coVarsOfCoVar v +coVarsOfCo (HoleCo h) = coVarsOfCoVar (coHoleCoVar h) + -- See Note [CoercionHoles and coercion free variables] +coVarsOfCo (AxiomInstCo _ _ as) = coVarsOfCos as +coVarsOfCo (UnivCo p _ t1 t2) = coVarsOfProv p `unionVarSet` coVarsOfTypes [t1, t2] +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 arg) = coVarsOfCo co `unionVarSet` coVarsOfCo arg +coVarsOfCo (KindCo co) = coVarsOfCo co +coVarsOfCo (SubCo co) = coVarsOfCo co +coVarsOfCo (AxiomRuleCo _ cs) = coVarsOfCos cs + +coVarsOfCoVar :: CoVar -> CoVarSet +coVarsOfCoVar v = unitVarSet v `unionVarSet` coVarsOfType (varType v) coVarsOfProv :: UnivCoProvenance -> CoVarSet coVarsOfProv UnsafeCoerceProv = emptyVarSet coVarsOfProv (PhantomProv co) = coVarsOfCo co coVarsOfProv (ProofIrrelProv co) = coVarsOfCo co coVarsOfProv (PluginProv _) = emptyVarSet -coVarsOfProv (HoleProv _) = emptyVarSet coVarsOfCos :: [Coercion] -> CoVarSet coVarsOfCos cos = mapUnionVarSet coVarsOfCo cos @@ -1558,6 +1832,41 @@ closeOverKindsList tvs = fvVarList $ closeOverKindsFV tvs closeOverKindsDSet :: DTyVarSet -> DTyVarSet closeOverKindsDSet = fvDVarSet . closeOverKindsFV . dVarSetElems +-- | Returns the free variables of a 'TyConBinder' that are in injective +-- positions. (See @Note [Kind annotations on TyConApps]@ in "TcSplice" for an +-- explanation of what an injective position is.) +injectiveVarsOfBinder :: TyConBinder -> FV +injectiveVarsOfBinder (Bndr tv vis) = + case vis of + AnonTCB -> injectiveVarsOfType (varType tv) + NamedTCB Required -> unitFV tv `unionFV` + injectiveVarsOfType (varType tv) + NamedTCB _ -> emptyFV + +-- | Returns the free variables of a 'Type' that are in injective positions. +-- (See @Note [Kind annotations on TyConApps]@ in "TcSplice" for an explanation +-- of what an injective position is.) +injectiveVarsOfType :: Type -> FV +injectiveVarsOfType = go + where + go ty | Just ty' <- coreView ty + = go ty' + go (TyVarTy v) = unitFV v `unionFV` go (tyVarKind v) + go (AppTy f a) = go f `unionFV` go a + go (FunTy ty1 ty2) = go ty1 `unionFV` go ty2 + go (TyConApp tc tys) = + case tyConInjectivityInfo tc of + NotInjective -> emptyFV + Injective inj -> mapUnionFV go $ + filterByList (inj ++ repeat True) tys + -- Oversaturated arguments to a tycon are + -- always injective, hence the repeat True + go (ForAllTy tvb ty) = tyCoFVsBndr tvb $ go (binderType tvb) + `unionFV` go ty + go LitTy{} = emptyFV + go (CastTy ty _) = go ty + go CoercionTy{} = emptyFV + -- | Returns True if this type has no free variables. Should be the same as -- isEmptyVarSet . tyCoVarsOfType, but faster in the non-forall case. noFreeVarsOfType :: Type -> Bool @@ -1570,25 +1879,33 @@ noFreeVarsOfType (LitTy _) = True noFreeVarsOfType (CastTy ty co) = noFreeVarsOfType ty && noFreeVarsOfCo co noFreeVarsOfType (CoercionTy co) = noFreeVarsOfCo co +noFreeVarsOfMCo :: MCoercion -> Bool +noFreeVarsOfMCo MRefl = True +noFreeVarsOfMCo (MCo co) = noFreeVarsOfCo co + +noFreeVarsOfTypes :: [Type] -> Bool +noFreeVarsOfTypes = all noFreeVarsOfType + -- | Returns True if this coercion has no free variables. Should be the same as -- isEmptyVarSet . tyCoVarsOfCo, but faster in the non-forall case. noFreeVarsOfCo :: Coercion -> Bool -noFreeVarsOfCo (Refl _ ty) = noFreeVarsOfType ty +noFreeVarsOfCo (Refl ty) = noFreeVarsOfType ty +noFreeVarsOfCo (GRefl _ ty co) = noFreeVarsOfType ty && noFreeVarsOfMCo co noFreeVarsOfCo (TyConAppCo _ _ args) = all noFreeVarsOfCo args noFreeVarsOfCo (AppCo c1 c2) = noFreeVarsOfCo c1 && noFreeVarsOfCo c2 noFreeVarsOfCo co@(ForAllCo {}) = isEmptyVarSet (tyCoVarsOfCo co) noFreeVarsOfCo (FunCo _ c1 c2) = noFreeVarsOfCo c1 && noFreeVarsOfCo c2 noFreeVarsOfCo (CoVarCo _) = False +noFreeVarsOfCo (HoleCo {}) = True -- I'm unsure; probably never happens noFreeVarsOfCo (AxiomInstCo _ _ args) = all noFreeVarsOfCo args noFreeVarsOfCo (UnivCo p _ t1 t2) = noFreeVarsOfProv p && noFreeVarsOfType t1 && noFreeVarsOfType t2 noFreeVarsOfCo (SymCo co) = noFreeVarsOfCo co noFreeVarsOfCo (TransCo co1 co2) = noFreeVarsOfCo co1 && noFreeVarsOfCo co2 -noFreeVarsOfCo (NthCo _ co) = noFreeVarsOfCo co +noFreeVarsOfCo (NthCo _ _ co) = noFreeVarsOfCo co noFreeVarsOfCo (LRCo _ co) = noFreeVarsOfCo co noFreeVarsOfCo (InstCo co1 co2) = noFreeVarsOfCo co1 && noFreeVarsOfCo co2 -noFreeVarsOfCo (CoherenceCo co1 co2) = noFreeVarsOfCo co1 && noFreeVarsOfCo co2 noFreeVarsOfCo (KindCo co) = noFreeVarsOfCo co noFreeVarsOfCo (SubCo co) = noFreeVarsOfCo co noFreeVarsOfCo (AxiomRuleCo _ cs) = all noFreeVarsOfCo cs @@ -1600,7 +1917,6 @@ noFreeVarsOfProv UnsafeCoerceProv = True noFreeVarsOfProv (PhantomProv co) = noFreeVarsOfCo co noFreeVarsOfProv (ProofIrrelProv co) = noFreeVarsOfCo co noFreeVarsOfProv (PluginProv {}) = True -noFreeVarsOfProv (HoleProv {}) = True -- matches with coVarsOfProv, but I'm unsure {- %************************************************************************ @@ -1628,7 +1944,7 @@ data TCvSubst = TCvSubst InScopeSet -- The in-scope type and kind variables TvSubstEnv -- Substitutes both type and kind variables CvSubstEnv -- Substitutes coercion variables - -- See Note [Apply Once] + -- See Note [Substitutions apply only once] -- and Note [Extending the TvSubstEnv] -- and Note [Substituting types and coercions] -- and Note [The substitution invariant] @@ -1636,21 +1952,51 @@ data TCvSubst -- | A substitution of 'Type's for 'TyVar's -- and 'Kind's for 'KindVar's type TvSubstEnv = TyVarEnv Type - -- A TvSubstEnv is used both inside a TCvSubst (with the apply-once - -- invariant discussed in Note [Apply Once]), and also independently - -- in the middle of matching, and unification (see Types.Unify) - -- So you have to look at the context to know if it's idempotent or - -- apply-once or whatever + -- NB: A TvSubstEnv is used + -- both inside a TCvSubst (with the apply-once invariant + -- discussed in Note [Substitutions apply only once], + -- and also independently in the middle of matching, + -- and unification (see Types.Unify). + -- So you have to look at the context to know if it's idempotent or + -- apply-once or whatever -- | A substitution of 'Coercion's for 'CoVar's type CvSubstEnv = CoVarEnv Coercion -{- -Note [Apply Once] -~~~~~~~~~~~~~~~~~ +{- Note [The substitution invariant] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When calling (substTy subst ty) it should be the case that +the in-scope set in the substitution is a superset of both: + + (SIa) The free vars of the range of the substitution + (SIb) The free vars of ty minus the domain of the substitution + +The same rules apply to other substitutions (notably CoreSubst.Subst) + +* Reason for (SIa). Consider + substTy [a :-> Maybe b] (forall b. b->a) + we must rename the forall b, to get + forall b2. b2 -> Maybe b + Making 'b' part of the in-scope set forces this renaming to + take place. + +* Reason for (SIb). Consider + substTy [a :-> Maybe b] (forall b. (a,b,x)) + Then if we use the in-scope set {b}, satisfying (SIa), there is + a danger we will rename the forall'd variable to 'x' by mistake, + getting this: + forall x. (Maybe b, x, x) + Breaking (SIb) caused the bug from #11371. + +Note: if the free vars of the range of the substitution are freshly created, +then the problems of (SIa) can't happen, and so it would be sound to +ignore (SIa). + +Note [Substitutions apply only once] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We use TCvSubsts to instantiate things, and we might instantiate forall a b. ty -\with the types +with the types [a, b], or [b, a]. So the substitution might go [a->b, b->a]. A similar situation arises in Core when we find a beta redex like @@ -1658,9 +2004,9 @@ when we find a beta redex like Then we also end up with a substitution that permutes type variables. Other variations happen to; for example [a -> (a, b)]. - **************************************************** - *** So a TCvSubst must be applied precisely once *** - **************************************************** + ******************************************************** + *** So a substitution must be applied precisely once *** + ******************************************************** A TCvSubst is not idempotent, but, unlike the non-idempotent substitution we use during unifications, it must not be repeatedly applied. @@ -1680,7 +2026,7 @@ nevertheless we add 'b' to the TvSubstEnv, because b's kind does change This invariant has several crucial consequences: -* In substTyVarBndr, we need extend the TvSubstEnv +* In substVarBndr, we need extend the TvSubstEnv - if the unique has changed - or if the kind has changed @@ -1703,25 +2049,6 @@ Note that the TvSubstEnv should *never* map a CoVar (built with the Id constructor) and the CvSubstEnv should *never* map a TyVar. Furthermore, the range of the TvSubstEnv should *never* include a type headed with CoercionTy. - -Note [The substitution invariant] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When calling (substTy subst ty) it should be the case that -the in-scope set in the substitution is a superset of both: - - * The free vars of the range of the substitution - * The free vars of ty minus the domain of the substitution - -If we want to substitute [a -> ty1, b -> ty2] I used to -think it was enough to generate an in-scope set that includes -fv(ty1,ty2). But that's not enough; we really should also take the -free vars of the type we are substituting into! Example: - (forall b. (a,b,x)) [a -> List b] -Then if we use the in-scope set {b}, there is a danger we will rename -the forall'd variable to 'x' by mistake, getting this: - (forall x. (List b, x, x)) - -Breaking this invariant caused the bug from #11371. -} emptyTvSubstEnv :: TvSubstEnv @@ -1773,6 +2100,10 @@ mkTvSubst :: InScopeSet -> TvSubstEnv -> TCvSubst -- ^ Make a TCvSubst with specified tyvar subst and empty covar subst mkTvSubst in_scope tenv = TCvSubst in_scope tenv emptyCvSubstEnv +mkCvSubst :: InScopeSet -> CvSubstEnv -> TCvSubst +-- ^ Make a TCvSubst with specified covar subst and empty tyvar subst +mkCvSubst in_scope cenv = TCvSubst in_scope emptyTvSubstEnv cenv + getTvSubstEnv :: TCvSubst -> TvSubstEnv getTvSubstEnv (TCvSubst _ env _) = env @@ -1831,14 +2162,20 @@ extendTCvSubst subst v ty | otherwise = pprPanic "extendTCvSubst" (ppr v <+> text "|->" <+> ppr ty) +extendTCvSubstWithClone :: TCvSubst -> TyCoVar -> TyCoVar -> TCvSubst +extendTCvSubstWithClone subst tcv + | isTyVar tcv = extendTvSubstWithClone subst tcv + | otherwise = extendCvSubstWithClone subst tcv + extendTvSubst :: TCvSubst -> TyVar -> Type -> TCvSubst extendTvSubst (TCvSubst in_scope tenv cenv) tv ty = TCvSubst in_scope (extendVarEnv tenv tv ty) cenv -extendTvSubstBinder :: TCvSubst -> TyBinder -> Type -> TCvSubst -extendTvSubstBinder subst (Named bndr) ty - = extendTvSubst subst (binderVar bndr) ty -extendTvSubstBinder subst (Anon _) _ +extendTvSubstBinderAndInScope :: TCvSubst -> TyCoBinder -> Type -> TCvSubst +extendTvSubstBinderAndInScope subst (Named (Bndr v _)) ty + = ASSERT( isTyVar v ) + extendTvSubstAndInScope subst v ty +extendTvSubstBinderAndInScope subst (Anon _) _ = subst extendTvSubstWithClone :: TCvSubst -> TyVar -> TyVar -> TCvSubst @@ -1873,6 +2210,10 @@ extendTvSubstList :: TCvSubst -> [Var] -> [Type] -> TCvSubst extendTvSubstList subst tvs tys = foldl2 extendTvSubst subst tvs tys +extendTCvSubstList :: TCvSubst -> [Var] -> [Type] -> TCvSubst +extendTCvSubstList subst tvs tys + = foldl2 extendTCvSubst subst tvs tys + unionTCvSubst :: TCvSubst -> TCvSubst -> TCvSubst -- Works when the ranges are disjoint unionTCvSubst (TCvSubst in_scope1 tenv1 cenv1) (TCvSubst in_scope2 tenv2 cenv2) @@ -1916,6 +2257,18 @@ zipCvSubst cvs cos where cenv = zipCoEnv cvs cos +zipTCvSubst :: [TyCoVar] -> [Type] -> TCvSubst +zipTCvSubst tcvs tys + | debugIsOn + , neLength tcvs tys + = pprTrace "zipTCvSubst" (ppr tcvs $$ ppr tys) emptyTCvSubst + | otherwise + = zip_tcvsubst tcvs tys (mkEmptyTCvSubst $ mkInScopeSet (tyCoVarsOfTypes tys)) + where zip_tcvsubst :: [TyCoVar] -> [Type] -> TCvSubst -> TCvSubst + zip_tcvsubst (tv:tvs) (ty:tys) subst + = zip_tcvsubst tvs tys (extendTCvSubst subst tv ty) + zip_tcvsubst _ _ subst = subst -- empty case + -- | Generates the in-scope set for the 'TCvSubst' from the types in the -- incoming environment. No CoVars, please! mkTvSubstPrs :: [(TyVar, Type)] -> TCvSubst @@ -2002,13 +2355,42 @@ sym (ForAllCo tv h g) ==> ForAllCo tv (sym h) (sym g[tv |-> tv |> sym h]) +Note [Substituting in a coercion hole] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It seems highly suspicious to be substituting in a coercion that still +has coercion holes. Yet, this can happen in a situation like this: + + f :: forall k. k :~: Type -> () + f Refl = let x :: forall (a :: k). [a] -> ... + x = ... + +When we check x's type signature, we require that k ~ Type. We indeed +know this due to the Refl pattern match, but the eager unifier can't +make use of givens. So, when we're done looking at x's type, a coercion +hole will remain. Then, when we're checking x's definition, we skolemise +x's type (in order to, e.g., bring the scoped type variable `a` into scope). +This requires performing a substitution for the fresh skolem variables. + +This subsitution needs to affect the kind of the coercion hole, too -- +otherwise, the kind will have an out-of-scope variable in it. More problematically +in practice (we won't actually notice the out-of-scope variable ever), skolems +in the kind might have too high a level, triggering a failure to uphold the +invariant that no free variables in a type have a higher level than the +ambient level in the type checker. In the event of having free variables in the +hole's kind, I'm pretty sure we'll always have an erroneous program, so we +don't need to worry what will happen when the hole gets filled in. After all, +a hole relating a locally-bound type variable will be unable to be solved. This +is why it's OK not to look through the IORef of a coercion hole during +substitution. + -} -- | Type substitution, see 'zipTvSubst' substTyWith :: HasCallStack => [TyVar] -> [Type] -> Type -> Type -- Works only if the domain of the substitution is a -- superset of the type being substituted into -substTyWith tvs tys = ASSERT( tvs `equalLength` tys ) +substTyWith tvs tys = {-#SCC "substTyWith" #-} + ASSERT( tvs `equalLength` tys ) substTy (zipTvSubst tvs tys) -- | Type substitution, see 'zipTvSubst'. Disables sanity checks. @@ -2086,17 +2468,16 @@ isValidTCvSubst (TCvSubst in_scope tenv cenv) = -- Note [The substitution invariant]. checkValidSubst :: HasCallStack => TCvSubst -> [Type] -> [Coercion] -> a -> a checkValidSubst subst@(TCvSubst in_scope tenv cenv) tys cos a - = ASSERT2( isValidTCvSubst subst, +-- TODO (RAE): Change back to ASSERT + = WARN( not (isValidTCvSubst subst), text "in_scope" <+> ppr in_scope $$ text "tenv" <+> ppr tenv $$ - text "tenvFVs" - <+> ppr (tyCoVarsOfTypesSet tenv) $$ + text "tenvFVs" <+> ppr (tyCoVarsOfTypesSet tenv) $$ text "cenv" <+> ppr cenv $$ - text "cenvFVs" - <+> ppr (tyCoVarsOfCosSet cenv) $$ + text "cenvFVs" <+> ppr (tyCoVarsOfCosSet cenv) $$ text "tys" <+> ppr tys $$ text "cos" <+> ppr cos ) - ASSERT2( tysCosFVsInScope, + WARN( not tysCosFVsInScope, text "in_scope" <+> ppr in_scope $$ text "tenv" <+> ppr tenv $$ text "cenv" <+> ppr cenv $$ @@ -2181,10 +2562,10 @@ subst_ty subst ty go (TyConApp tc tys) = let args = map go tys in args `seqList` TyConApp tc args go (FunTy arg res) = (FunTy $! go arg) $! go res - go (ForAllTy (TvBndr tv vis) ty) - = case substTyVarBndrUnchecked subst tv of + go (ForAllTy (Bndr tv vis) ty) + = case substVarBndrUnchecked subst tv of (subst', tv') -> - (ForAllTy $! ((TvBndr $! tv') vis)) $! + (ForAllTy $! ((Bndr $! tv') vis)) $! (subst_ty subst' ty) go (LitTy n) = LitTy $! n go (CastTy ty co) = (mkCastTy $! (go ty)) $! (subst_co subst co) @@ -2200,6 +2581,14 @@ substTyVar (TCvSubst _ tenv _) tv substTyVars :: TCvSubst -> [TyVar] -> [Type] substTyVars subst = map $ substTyVar subst +substTyCoVars :: TCvSubst -> [TyCoVar] -> [Type] +substTyCoVars subst = map $ substTyCoVar subst + +substTyCoVar :: TCvSubst -> TyCoVar -> Type +substTyCoVar subst tv + | isTyVar tv = substTyVar subst tv + | otherwise = CoercionTy $ substCoVar subst tv + lookupTyVar :: TCvSubst -> TyVar -> Maybe Type -- See Note [Extending the TCvSubst] lookupTyVar (TCvSubst _ tenv _) tv @@ -2239,14 +2628,20 @@ subst_co subst co go_ty :: Type -> Type go_ty = subst_ty subst + go_mco :: MCoercion -> MCoercion + go_mco MRefl = MRefl + go_mco (MCo co) = MCo (go co) + go :: Coercion -> Coercion - go (Refl r ty) = mkReflCo r $! go_ty ty + go (Refl ty) = mkNomReflCo $! (go_ty ty) + go (GRefl r ty mco) = (mkGReflCo r $! (go_ty ty)) $! (go_mco mco) go (TyConAppCo r tc args)= let args' = map go args in args' `seqList` mkTyConAppCo r tc args' go (AppCo co arg) = (mkAppCo $! go co) $! go arg go (ForAllCo tv kind_co co) - = case substForAllCoBndrUnchecked subst tv kind_co of { (subst', tv', kind_co') -> - ((mkForAllCo $! tv') $! kind_co') $! subst_co subst' co } + = case substForAllCoBndrUnchecked subst tv kind_co of + (subst', tv', kind_co') -> + ((mkForAllCo $! tv') $! kind_co') $! subst_co subst' co go (FunCo r co1 co2) = (mkFunCo r $! go co1) $! go co2 go (CoVarCo cv) = substCoVar subst cv go (AxiomInstCo con ind cos) = mkAxiomInstCo con ind $! map go cos @@ -2254,51 +2649,60 @@ subst_co subst co (go_ty t1)) $! (go_ty t2) go (SymCo co) = mkSymCo $! (go co) go (TransCo co1 co2) = (mkTransCo $! (go co1)) $! (go co2) - go (NthCo d co) = mkNthCo d $! (go co) + go (NthCo r d co) = mkNthCo r d $! (go co) go (LRCo lr co) = mkLRCo lr $! (go co) go (InstCo co arg) = (mkInstCo $! (go co)) $! go arg - go (CoherenceCo co1 co2) = (mkCoherenceCo $! (go co1)) $! (go co2) go (KindCo co) = mkKindCo $! (go co) go (SubCo co) = mkSubCo $! (go co) go (AxiomRuleCo c cs) = let cs1 = map go cs in cs1 `seqList` AxiomRuleCo c cs1 + go (HoleCo h) = HoleCo $! go_hole h go_prov UnsafeCoerceProv = UnsafeCoerceProv go_prov (PhantomProv kco) = PhantomProv (go kco) go_prov (ProofIrrelProv kco) = ProofIrrelProv (go kco) go_prov p@(PluginProv _) = p - go_prov p@(HoleProv _) = p - -- NB: this last case is a little suspicious, but we need it. Originally, - -- there was a panic here, but it triggered from deeplySkolemise. Because - -- we only skolemise tyvars that are manually bound, this operation makes - -- sense, even over a coercion with holes. -substForAllCoBndr :: TCvSubst -> TyVar -> Coercion -> (TCvSubst, TyVar, Coercion) + -- See Note [Substituting in a coercion hole] + go_hole h@(CoercionHole { ch_co_var = cv }) + = h { ch_co_var = updateVarType go_ty cv } + +substForAllCoBndr :: TCvSubst -> TyCoVar -> KindCoercion + -> (TCvSubst, TyCoVar, Coercion) substForAllCoBndr subst - = substForAllCoBndrCallback False (substCo subst) subst + = substForAllCoBndrUsing False (substCo subst) subst -- | Like 'substForAllCoBndr', but disables sanity checks. -- The problems that the sanity checks in substCo catch are described in -- Note [The substitution invariant]. -- The goal of #11371 is to migrate all the calls of substCoUnchecked to -- substCo and remove this function. Please don't use in new code. -substForAllCoBndrUnchecked :: TCvSubst -> TyVar -> Coercion -> (TCvSubst, TyVar, Coercion) +substForAllCoBndrUnchecked :: TCvSubst -> TyCoVar -> KindCoercion + -> (TCvSubst, TyCoVar, Coercion) substForAllCoBndrUnchecked subst - = substForAllCoBndrCallback False (substCoUnchecked subst) subst + = substForAllCoBndrUsing False (substCoUnchecked subst) subst -- See Note [Sym and ForAllCo] -substForAllCoBndrCallback :: Bool -- apply sym to binder? - -> (Coercion -> Coercion) -- transformation to kind co - -> TCvSubst -> TyVar -> Coercion - -> (TCvSubst, TyVar, Coercion) -substForAllCoBndrCallback sym sco (TCvSubst in_scope tenv cenv) - old_var old_kind_co - = ( TCvSubst (in_scope `extendInScopeSet` new_var) new_env cenv +substForAllCoBndrUsing :: Bool -- apply sym to binder? + -> (Coercion -> Coercion) -- transformation to kind co + -> TCvSubst -> TyCoVar -> KindCoercion + -> (TCvSubst, TyCoVar, KindCoercion) +substForAllCoBndrUsing sym sco subst old_var + | isTyVar old_var = substForAllCoTyVarBndrUsing sym sco subst old_var + | otherwise = substForAllCoCoVarBndrUsing sym sco subst old_var + +substForAllCoTyVarBndrUsing :: Bool -- apply sym to binder? + -> (Coercion -> Coercion) -- transformation to kind co + -> TCvSubst -> TyVar -> KindCoercion + -> (TCvSubst, TyVar, KindCoercion) +substForAllCoTyVarBndrUsing sym sco (TCvSubst in_scope tenv cenv) old_var old_kind_co + = ASSERT( isTyVar old_var ) + ( TCvSubst (in_scope `extendInScopeSet` new_var) new_env cenv , new_var, new_kind_co ) where new_env | no_change && not sym = delVarEnv tenv old_var | sym = extendVarEnv tenv old_var $ - TyVarTy new_var `CastTy` new_kind_co + TyVarTy new_var `CastTy` new_kind_co | otherwise = extendVarEnv tenv old_var (TyVarTy new_var) no_kind_change = noFreeVarsOfCo old_kind_co @@ -2308,9 +2712,38 @@ substForAllCoBndrCallback sym sco (TCvSubst in_scope tenv cenv) | otherwise = sco old_kind_co Pair new_ki1 _ = coercionKind new_kind_co + -- We could do substitution to (tyVarKind old_var). We don't do so because + -- we already substituted new_kind_co, which contains the kind information + -- we want. We don't want to do substitution once more. Also, in most cases, + -- new_kind_co is a Refl, in which case coercionKind is really fast. new_var = uniqAway in_scope (setTyVarKind old_var new_ki1) +substForAllCoCoVarBndrUsing :: Bool -- apply sym to binder? + -> (Coercion -> Coercion) -- transformation to kind co + -> TCvSubst -> CoVar -> KindCoercion + -> (TCvSubst, CoVar, KindCoercion) +substForAllCoCoVarBndrUsing sym sco (TCvSubst in_scope tenv cenv) + old_var old_kind_co + = ASSERT( isCoVar old_var ) + ( TCvSubst (in_scope `extendInScopeSet` new_var) tenv new_cenv + , new_var, new_kind_co ) + where + new_cenv | no_change && not sym = delVarEnv cenv old_var + | otherwise = extendVarEnv cenv old_var (mkCoVarCo new_var) + + no_kind_change = noFreeVarsOfCo old_kind_co + no_change = no_kind_change && (new_var == old_var) + + new_kind_co | no_kind_change = old_kind_co + | otherwise = sco old_kind_co + + Pair h1 h2 = coercionKind new_kind_co + + new_var = uniqAway in_scope $ mkCoVar (varName old_var) new_var_type + new_var_type | sym = h2 + | otherwise = h1 + substCoVar :: TCvSubst -> CoVar -> Coercion substCoVar (TCvSubst _ _ cenv) cv = case lookupVarEnv cenv cv of @@ -2320,25 +2753,45 @@ substCoVar (TCvSubst _ _ cenv) cv substCoVars :: TCvSubst -> [CoVar] -> [Coercion] substCoVars subst cvs = map (substCoVar subst) cvs -lookupCoVar :: TCvSubst -> Var -> Maybe Coercion +lookupCoVar :: TCvSubst -> Var -> Maybe Coercion lookupCoVar (TCvSubst _ _ cenv) v = lookupVarEnv cenv v substTyVarBndr :: HasCallStack => TCvSubst -> TyVar -> (TCvSubst, TyVar) -substTyVarBndr = substTyVarBndrCallback substTy +substTyVarBndr = substTyVarBndrUsing substTy + +substTyVarBndrs :: HasCallStack => TCvSubst -> [TyVar] -> (TCvSubst, [TyVar]) +substTyVarBndrs = mapAccumL substTyVarBndr + +substVarBndr :: HasCallStack => TCvSubst -> TyCoVar -> (TCvSubst, TyCoVar) +substVarBndr = substVarBndrUsing substTy + +substVarBndrs :: HasCallStack => TCvSubst -> [TyCoVar] -> (TCvSubst, [TyCoVar]) +substVarBndrs = mapAccumL substVarBndr --- | Like 'substTyVarBndr' but disables sanity checks. +substCoVarBndr :: HasCallStack => TCvSubst -> CoVar -> (TCvSubst, CoVar) +substCoVarBndr = substCoVarBndrUsing substTy + +-- | Like 'substVarBndr', but disables sanity checks. -- The problems that the sanity checks in substTy catch are described in -- Note [The substitution invariant]. -- The goal of #11371 is to migrate all the calls of substTyUnchecked to -- substTy and remove this function. Please don't use in new code. -substTyVarBndrUnchecked :: TCvSubst -> TyVar -> (TCvSubst, TyVar) -substTyVarBndrUnchecked = substTyVarBndrCallback substTyUnchecked +substVarBndrUnchecked :: TCvSubst -> TyCoVar -> (TCvSubst, TyCoVar) +substVarBndrUnchecked = substVarBndrUsing substTyUnchecked + +substVarBndrUsing :: (TCvSubst -> Type -> Type) + -> TCvSubst -> TyCoVar -> (TCvSubst, TyCoVar) +substVarBndrUsing subst_fn subst v + | isTyVar v = substTyVarBndrUsing subst_fn subst v + | otherwise = substCoVarBndrUsing subst_fn subst v -- | Substitute a tyvar in a binding position, returning an -- extended subst and a new tyvar. -substTyVarBndrCallback :: (TCvSubst -> Type -> Type) -- ^ the subst function - -> TCvSubst -> TyVar -> (TCvSubst, TyVar) -substTyVarBndrCallback subst_fn subst@(TCvSubst in_scope tenv cenv) old_var +-- Use the supplied function to substitute in the kind +substTyVarBndrUsing + :: (TCvSubst -> Type -> Type) -- ^ Use this to substitute in the kind + -> TCvSubst -> TyVar -> (TCvSubst, TyVar) +substTyVarBndrUsing subst_fn subst@(TCvSubst in_scope tenv cenv) old_var = ASSERT2( _no_capture, pprTyVar old_var $$ pprTyVar new_var $$ ppr subst ) ASSERT( isTyVar old_var ) (TCvSubst (in_scope `extendInScopeSet` new_var) new_env cenv, new_var) @@ -2367,13 +2820,18 @@ substTyVarBndrCallback subst_fn subst@(TCvSubst in_scope tenv cenv) old_var setTyVarKind old_var (subst_fn subst old_ki) -- The uniqAway part makes sure the new variable is not already in scope -substCoVarBndr :: TCvSubst -> CoVar -> (TCvSubst, CoVar) -substCoVarBndr subst@(TCvSubst in_scope tenv cenv) old_var +-- | Substitute a covar in a binding position, returning an +-- extended subst and a new covar. +-- Use the supplied function to substitute in the kind +substCoVarBndrUsing + :: (TCvSubst -> Type -> Type) + -> TCvSubst -> CoVar -> (TCvSubst, CoVar) +substCoVarBndrUsing subst_fn subst@(TCvSubst in_scope tenv cenv) old_var = ASSERT( isCoVar old_var ) (TCvSubst (in_scope `extendInScopeSet` new_var) tenv new_cenv, new_var) where new_co = mkCoVarCo new_var - no_kind_change = all noFreeVarsOfType [t1, t2] + no_kind_change = noFreeVarsOfTypes [t1, t2] no_change = new_var == old_var && no_kind_change new_cenv | no_change = delVarEnv cenv old_var @@ -2383,8 +2841,8 @@ substCoVarBndr subst@(TCvSubst in_scope tenv cenv) old_var subst_old_var = mkCoVar (varName old_var) new_var_type (_, _, t1, t2, role) = coVarKindsTypesRole old_var - t1' = substTy subst t1 - t2' = substTy subst t2 + t1' = subst_fn subst t1 + t2' = subst_fn subst t2 new_var_type = mkCoercionType role t1' t2' -- It's important to do the substitution for coercions, -- because they can have free type variables @@ -2425,17 +2883,28 @@ defined to use this. @pprParendType@ is the same, except it puts parens around the type, except for the atomic cases. @pprParendType@ works just by setting the initial context precedence very high. +Note that any function which pretty-prints a @Type@ first converts the @Type@ +to an @IfaceType@. See Note [IfaceType and pretty-printing] in IfaceType. + See Note [Precedence in types] in BasicTypes. -} ------------------- +-------------------------------------------------------- +-- When pretty-printing types, we convert to IfaceType, +-- and pretty-print that. +-- See Note [Pretty printing via IfaceSyn] in PprTyThing +-------------------------------------------------------- pprType, pprParendType :: Type -> SDoc -pprType = pprPrecType TopPrec -pprParendType = pprPrecType TyConPrec +pprType = pprPrecType topPrec +pprParendType = pprPrecType appPrec -pprPrecType :: TyPrec -> Type -> SDoc -pprPrecType prec ty = pprPrecIfaceType prec (tidyToIfaceType ty) +pprPrecType :: PprPrec -> Type -> SDoc +pprPrecType prec ty + = getPprStyle $ \sty -> + if debugStyle sty -- Use pprDebugType when in + then debug_ppr_ty prec ty -- when in debug-style + else pprPrecIfaceType prec (tidyToIfaceTypeSty ty sty) pprTyLit :: TyLit -> SDoc pprTyLit = pprIfaceTyLit . toIfaceTyLit @@ -2444,6 +2913,12 @@ pprKind, pprParendKind :: Kind -> SDoc pprKind = pprType pprParendKind = pprParendType +tidyToIfaceTypeSty :: Type -> PprStyle -> IfaceType +tidyToIfaceTypeSty ty sty + | userStyle sty = tidyToIfaceType ty + | otherwise = toIfaceTypeX (tyCoVarsOfType ty) ty + -- in latter case, don't tidy, as we'll be printing uniques. + tidyToIfaceType :: Type -> IfaceType -- It's vital to tidy before converting to an IfaceType -- or nested binders will become indistinguishable! @@ -2457,15 +2932,38 @@ tidyToIfaceType ty = toIfaceTypeX (mkVarSet free_tcvs) (tidyType env ty) free_tcvs = tyCoVarsOfTypeWellScoped ty ------------ +pprCo, pprParendCo :: Coercion -> SDoc +pprCo co = getPprStyle $ \ sty -> pprIfaceCoercion (tidyToIfaceCoSty co sty) +pprParendCo co = getPprStyle $ \ sty -> pprParendIfaceCoercion (tidyToIfaceCoSty co sty) + +tidyToIfaceCoSty :: Coercion -> PprStyle -> IfaceCoercion +tidyToIfaceCoSty co sty + | userStyle sty = tidyToIfaceCo co + | otherwise = toIfaceCoercionX (tyCoVarsOfCo co) co + -- in latter case, don't tidy, as we'll be printing uniques. + +tidyToIfaceCo :: Coercion -> IfaceCoercion +-- It's vital to tidy before converting to an IfaceType +-- or nested binders will become indistinguishable! +-- +-- Also for the free type variables, tell toIfaceCoercionX to +-- leave them as IfaceFreeCoVar. This is super-important +-- for debug printing. +tidyToIfaceCo co = toIfaceCoercionX (mkVarSet free_tcvs) (tidyCo env co) + where + env = tidyFreeTyCoVars emptyTidyEnv free_tcvs + free_tcvs = toposortTyVars $ tyCoVarsOfCoList co + +------------ pprClassPred :: Class -> [Type] -> SDoc pprClassPred clas tys = pprTypeApp (classTyCon clas) tys ------------ pprTheta :: ThetaType -> SDoc -pprTheta = pprIfaceContext TopPrec . map tidyToIfaceType +pprTheta = pprIfaceContext topPrec . map tidyToIfaceType pprParendTheta :: ThetaType -> SDoc -pprParendTheta = pprIfaceContext TyConPrec . map tidyToIfaceType +pprParendTheta = pprIfaceContext appPrec . map tidyToIfaceType pprThetaArrowTy :: ThetaType -> SDoc pprThetaArrowTy = pprIfaceContextArr . map tidyToIfaceType @@ -2478,22 +2976,21 @@ instance Outputable TyLit where ppr = pprTyLit ------------------ - pprSigmaType :: Type -> SDoc pprSigmaType = pprIfaceSigmaType ShowForAllWhen . tidyToIfaceType -pprForAll :: [TyVarBinder] -> SDoc +pprForAll :: [TyCoVarBinder] -> SDoc pprForAll tvs = pprIfaceForAll (map toIfaceForAllBndr tvs) -- | Print a user-level forall; see Note [When to print foralls] -pprUserForAll :: [TyVarBinder] -> SDoc +pprUserForAll :: [TyCoVarBinder] -> SDoc pprUserForAll = pprUserIfaceForAll . map toIfaceForAllBndr -pprTvBndrs :: [TyVarBinder] -> SDoc -pprTvBndrs tvs = sep (map pprTvBndr tvs) +pprTCvBndrs :: [TyCoVarBinder] -> SDoc +pprTCvBndrs tvs = sep (map pprTCvBndr tvs) -pprTvBndr :: TyVarBinder -> SDoc -pprTvBndr = pprTyVar . binderVar +pprTCvBndr :: TyCoVarBinder -> SDoc +pprTCvBndr = pprTyVar . binderVar pprTyVars :: [TyVar] -> SDoc pprTyVars tvs = sep (map pprTyVar tvs) @@ -2509,16 +3006,67 @@ pprTyVar tv where kind = tyVarKind tv -instance Outputable TyBinder where +instance Outputable TyCoBinder where ppr (Anon ty) = text "[anon]" <+> ppr ty - ppr (Named (TvBndr v Required)) = ppr v - ppr (Named (TvBndr v Specified)) = char '@' <> ppr v - ppr (Named (TvBndr v Inferred)) = braces (ppr v) + ppr (Named (Bndr v Required)) = ppr v + ppr (Named (Bndr v Specified)) = char '@' <> ppr v + ppr (Named (Bndr v Inferred)) = braces (ppr v) ----------------- instance Outputable Coercion where -- defined here to avoid orphans ppr = pprCo +debugPprType :: Type -> SDoc +-- ^ debugPprType is a simple pretty printer that prints a type +-- without going through IfaceType. It does not format as prettily +-- as the normal route, but it's much more direct, and that can +-- be useful for debugging. E.g. with -dppr-debug it prints the +-- kind on type-variable /occurrences/ which the normal route +-- fundamentally cannot do. +debugPprType ty = debug_ppr_ty topPrec ty + +debug_ppr_ty :: PprPrec -> Type -> SDoc +debug_ppr_ty _ (LitTy l) + = ppr l + +debug_ppr_ty _ (TyVarTy tv) + = ppr tv -- With -dppr-debug we get (tv :: kind) + +debug_ppr_ty prec (FunTy arg res) + = maybeParen prec funPrec $ + sep [debug_ppr_ty funPrec arg, arrow <+> debug_ppr_ty prec res] + +debug_ppr_ty prec (TyConApp tc tys) + | null tys = ppr tc + | otherwise = maybeParen prec appPrec $ + hang (ppr tc) 2 (sep (map (debug_ppr_ty appPrec) tys)) + +debug_ppr_ty prec (AppTy t1 t2) + = hang (debug_ppr_ty prec t1) + 2 (debug_ppr_ty appPrec t2) + +debug_ppr_ty prec (CastTy ty co) + = maybeParen prec topPrec $ + hang (debug_ppr_ty topPrec ty) + 2 (text "|>" <+> ppr co) + +debug_ppr_ty _ (CoercionTy co) + = parens (text "CO" <+> ppr co) + +debug_ppr_ty prec ty@(ForAllTy {}) + | (tvs, body) <- split ty + = maybeParen prec funPrec $ + hang (text "forall" <+> fsep (map ppr tvs) <> dot) + -- The (map ppr tvs) will print kind-annotated + -- tvs, because we are (usually) in debug-style + 2 (ppr body) + where + split ty | ForAllTy tv ty' <- ty + , (tvs, body) <- split ty' + = (tv:tvs, body) + | otherwise + = ([], ty) + {- Note [When to print foralls] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2536,7 +3084,7 @@ This catches common situations, such as a type siguature which means f :: forall k. forall (m :: k->*) (a :: k). m a We really want to see both the "forall k" and the kind signatures -on m and a. The latter comes from pprTvBndr. +on m and a. The latter comes from pprTCvBndr. Note [Infix type variables] ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2566,37 +3114,20 @@ pprDataCons = sepWithVBars . fmap pprDataConWithArgs . tyConDataCons pprDataConWithArgs :: DataCon -> SDoc pprDataConWithArgs dc = sep [forAllDoc, thetaDoc, ppr dc <+> argsDoc] where - (_univ_tvs, _ex_tvs, eq_spec, theta, arg_tys, _res_ty) = dataConFullSig dc - univ_bndrs = dataConUnivTyVarBinders dc - ex_bndrs = dataConExTyVarBinders dc - forAllDoc = pprUserForAll $ (filterEqSpec eq_spec univ_bndrs ++ ex_bndrs) - thetaDoc = pprThetaArrowTy theta - argsDoc = hsep (fmap pprParendType arg_tys) + (_univ_tvs, _ex_tvs, _eq_spec, theta, arg_tys, _res_ty) = dataConFullSig dc + user_bndrs = dataConUserTyVarBinders dc + forAllDoc = pprUserForAll user_bndrs + thetaDoc = pprThetaArrowTy theta + argsDoc = hsep (fmap pprParendType arg_tys) pprTypeApp :: TyCon -> [Type] -> SDoc pprTypeApp tc tys - = pprIfaceTypeApp TopPrec (toIfaceTyCon tc) + = pprIfaceTypeApp topPrec (toIfaceTyCon tc) (toIfaceTcArgs tc tys) -- TODO: toIfaceTcArgs seems rather wasteful here -pprTcAppCo :: TyPrec -> (TyPrec -> Coercion -> SDoc) - -> TyCon -> [Coercion] -> SDoc -pprTcAppCo p _pp tc cos - = pprIfaceCoTcApp p (toIfaceTyCon tc) (map toIfaceCoercion cos) - ------------------ - -pprPrefixApp :: TyPrec -> SDoc -> [SDoc] -> SDoc -pprPrefixApp = pprIfacePrefixApp - ----------------- -pprArrowChain :: TyPrec -> [SDoc] -> SDoc --- pprArrowChain p [a,b,c] generates a -> b -> c -pprArrowChain _ [] = empty -pprArrowChain p (arg:args) = maybeParen p FunPrec $ - sep [arg, sep (map (arrow <+>) args)] - ppSuggestExplicitKinds :: SDoc -- Print a helpful suggstion about -fprint-explicit-kinds, -- if it is not already on @@ -2617,32 +3148,32 @@ ppSuggestExplicitKinds -- an interface file. -- -- It doesn't change the uniques at all, just the print names. -tidyTyCoVarBndrs :: TidyEnv -> [TyCoVar] -> (TidyEnv, [TyCoVar]) -tidyTyCoVarBndrs (occ_env, subst) tvs - = mapAccumL tidyTyCoVarBndr tidy_env' tvs +tidyVarBndrs :: TidyEnv -> [TyCoVar] -> (TidyEnv, [TyCoVar]) +tidyVarBndrs (occ_env, subst) tvs + = mapAccumL tidyVarBndr tidy_env' tvs where -- Seed the occ_env with clashes among the names, see -- Node [Tidying multiple names at once] in OccName - -- Se still go through tidyTyCoVarBndr so that each kind variable is tidied + -- Se still go through tidyVarBndr so that each kind variable is tidied -- with the correct tidy_env occs = map getHelpfulOccName tvs tidy_env' = (avoidClashesOccEnv occ_env occs, subst) -tidyTyCoVarBndr :: TidyEnv -> TyCoVar -> (TidyEnv, TyCoVar) -tidyTyCoVarBndr tidy_env@(occ_env, subst) tyvar - = case tidyOccName occ_env (getHelpfulOccName tyvar) of - (occ_env', occ') -> ((occ_env', subst'), tyvar') +tidyVarBndr :: TidyEnv -> TyCoVar -> (TidyEnv, TyCoVar) +tidyVarBndr tidy_env@(occ_env, subst) var + = case tidyOccName occ_env (getHelpfulOccName var) of + (occ_env', occ') -> ((occ_env', subst'), var') where - subst' = extendVarEnv subst tyvar tyvar' - tyvar' = setTyVarKind (setTyVarName tyvar name') kind' - kind' = tidyKind tidy_env (tyVarKind tyvar) + subst' = extendVarEnv subst var var' + var' = setVarType (setVarName var name') type' + type' = tidyType tidy_env (varType var) name' = tidyNameOcc name occ' - name = tyVarName tyvar + name = varName var getHelpfulOccName :: TyCoVar -> OccName -getHelpfulOccName tyvar = occ1 +getHelpfulOccName var = occ1 where - name = tyVarName tyvar + name = varName var occ = getOccName name -- A TcTyVar with a System Name is probably a unification variable; -- when we tidy them we give them a trailing "0" (or 1 etc) @@ -2650,21 +3181,21 @@ getHelpfulOccName tyvar = occ1 -- Plus, indicating a unification variable in this way is a -- helpful clue for users occ1 | isSystemName name - , isTcTyVar tyvar + , isTcTyVar var = mkTyVarOcc (occNameString occ ++ "0") | otherwise = occ -tidyTyVarBinder :: TidyEnv -> TyVarBndr TyVar vis - -> (TidyEnv, TyVarBndr TyVar vis) -tidyTyVarBinder tidy_env (TvBndr tv vis) - = (tidy_env', TvBndr tv' vis) +tidyTyCoVarBinder :: TidyEnv -> VarBndr TyCoVar vis + -> (TidyEnv, VarBndr TyCoVar vis) +tidyTyCoVarBinder tidy_env (Bndr tv vis) + = (tidy_env', Bndr tv' vis) where - (tidy_env', tv') = tidyTyCoVarBndr tidy_env tv + (tidy_env', tv') = tidyVarBndr tidy_env tv -tidyTyVarBinders :: TidyEnv -> [TyVarBndr TyVar vis] - -> (TidyEnv, [TyVarBndr TyVar vis]) -tidyTyVarBinders = mapAccumL tidyTyVarBinder +tidyTyCoVarBinders :: TidyEnv -> [VarBndr TyCoVar vis] + -> (TidyEnv, [VarBndr TyCoVar vis]) +tidyTyCoVarBinders = mapAccumL tidyTyCoVarBinder --------------- tidyFreeTyCoVars :: TidyEnv -> [TyCoVar] -> TidyEnv @@ -2673,7 +3204,7 @@ tidyFreeTyCoVars :: TidyEnv -> [TyCoVar] -> TidyEnv tidyFreeTyCoVars (full_occ_env, var_env) tyvars = fst (tidyOpenTyCoVars (full_occ_env, var_env) tyvars) - --------------- +--------------- tidyOpenTyCoVars :: TidyEnv -> [TyCoVar] -> (TidyEnv, [TyCoVar]) tidyOpenTyCoVars env tyvars = mapAccumL tidyOpenTyCoVar env tyvars @@ -2681,19 +3212,19 @@ tidyOpenTyCoVars env tyvars = mapAccumL tidyOpenTyCoVar env tyvars tidyOpenTyCoVar :: TidyEnv -> TyCoVar -> (TidyEnv, TyCoVar) -- ^ Treat a new 'TyCoVar' as a binder, and give it a fresh tidy name -- using the environment if one has not already been allocated. See --- also 'tidyTyCoVarBndr' +-- also 'tidyVarBndr' tidyOpenTyCoVar env@(_, subst) tyvar = case lookupVarEnv subst tyvar of Just tyvar' -> (env, tyvar') -- Already substituted Nothing -> let env' = tidyFreeTyCoVars env (tyCoVarsOfTypeList (tyVarKind tyvar)) - in tidyTyCoVarBndr env' tyvar -- Treat it as a binder + in tidyVarBndr env' tyvar -- Treat it as a binder --------------- -tidyTyVarOcc :: TidyEnv -> TyVar -> TyVar -tidyTyVarOcc env@(_, subst) tv +tidyTyCoVarOcc :: TidyEnv -> TyCoVar -> TyCoVar +tidyTyCoVarOcc env@(_, subst) tv = case lookupVarEnv subst tv of - Nothing -> updateTyVarKind (tidyType env) tv + Nothing -> updateVarType (tidyType env) tv Just tv' -> tv' --------------- @@ -2703,7 +3234,7 @@ tidyTypes env tys = map (tidyType env) tys --------------- tidyType :: TidyEnv -> Type -> Type tidyType _ (LitTy n) = LitTy n -tidyType env (TyVarTy tv) = TyVarTy (tidyTyVarOcc env tv) +tidyType env (TyVarTy tv) = TyVarTy (tidyTyCoVarOcc env tv) tidyType env (TyConApp tycon tys) = let args = tidyTypes env tys in args `seqList` TyConApp tycon args tidyType env (AppTy fun arg) = (AppTy $! (tidyType env fun)) $! (tidyType env arg) @@ -2711,7 +3242,7 @@ tidyType env (FunTy fun arg) = (FunTy $! (tidyType env fun)) $! (tidyType e tidyType env (ty@(ForAllTy{})) = mkForAllTys' (zip tvs' vis) $! tidyType env' body_ty where (tvs, vis, body_ty) = splitForAllTys' ty - (env', tvs') = tidyTyCoVarBndrs env tvs + (env', tvs') = tidyVarBndrs env tvs tidyType env (CastTy ty co) = (CastTy $! tidyType env ty) $! (tidyCo env co) tidyType env (CoercionTy co) = CoercionTy $! (tidyCo env co) @@ -2719,16 +3250,16 @@ tidyType env (CoercionTy co) = CoercionTy $! (tidyCo env co) -- The following two functions differ from mkForAllTys and splitForAllTys in that -- they expect/preserve the ArgFlag argument. Thes belong to types/Type.hs, but -- how should they be named? -mkForAllTys' :: [(TyVar, ArgFlag)] -> Type -> Type +mkForAllTys' :: [(TyCoVar, ArgFlag)] -> Type -> Type mkForAllTys' tvvs ty = foldr strictMkForAllTy ty tvvs where - strictMkForAllTy (tv,vis) ty = (ForAllTy $! ((TvBndr $! tv) $! vis)) $! ty + strictMkForAllTy (tv,vis) ty = (ForAllTy $! ((Bndr $! tv) $! vis)) $! ty -splitForAllTys' :: Type -> ([TyVar], [ArgFlag], Type) +splitForAllTys' :: Type -> ([TyCoVar], [ArgFlag], Type) splitForAllTys' ty = go ty [] [] where - go (ForAllTy (TvBndr tv vis) ty) tvs viss = go ty (tv:tvs) (vis:viss) - go ty tvs viss = (reverse tvs, reverse viss, ty) + go (ForAllTy (Bndr tv vis) ty) tvs viss = go ty (tv:tvs) (vis:viss) + go ty tvs viss = (reverse tvs, reverse viss, ty) --------------- @@ -2767,28 +3298,32 @@ tidyCo :: TidyEnv -> Coercion -> Coercion tidyCo env@(_, subst) co = go co where - go (Refl r ty) = Refl r (tidyType env ty) + go_mco MRefl = MRefl + go_mco (MCo co) = MCo (go co) + + go (Refl ty) = Refl (tidyType env ty) + go (GRefl r ty mco) = GRefl r (tidyType env ty) $! go_mco mco go (TyConAppCo r tc cos) = let args = map go cos in args `seqList` TyConAppCo r tc args go (AppCo co1 co2) = (AppCo $! go co1) $! go co2 go (ForAllCo tv h co) = ((ForAllCo $! tvp) $! (go h)) $! (tidyCo envp co) - where (envp, tvp) = tidyTyCoVarBndr env tv + where (envp, tvp) = tidyVarBndr env tv -- the case above duplicates a bit of work in tidying h and the kind -- of tv. But the alternative is to use coercionKind, which seems worse. go (FunCo r co1 co2) = (FunCo r $! go co1) $! go co2 go (CoVarCo cv) = case lookupVarEnv subst cv of Nothing -> CoVarCo cv Just cv' -> CoVarCo cv' + go (HoleCo h) = HoleCo h go (AxiomInstCo con ind cos) = let args = map go cos in args `seqList` AxiomInstCo con ind args go (UnivCo p r t1 t2) = (((UnivCo $! (go_prov p)) $! r) $! tidyType env t1) $! tidyType env t2 go (SymCo co) = SymCo $! go co go (TransCo co1 co2) = (TransCo $! go co1) $! go co2 - go (NthCo d co) = NthCo d $! go co + go (NthCo r d co) = NthCo r d $! go co go (LRCo lr co) = LRCo lr $! go co go (InstCo co ty) = (InstCo $! go co) $! go ty - go (CoherenceCo co1 co2) = (CoherenceCo $! go co1) $! go co2 go (KindCo co) = KindCo $! go co go (SubCo co) = SubCo $! go co go (AxiomRuleCo ax cos) = let cos1 = tidyCos env cos @@ -2798,7 +3333,6 @@ tidyCo env@(_, subst) co go_prov (PhantomProv co) = PhantomProv (go co) go_prov (ProofIrrelProv co) = ProofIrrelProv (go co) go_prov p@(PluginProv _) = p - go_prov p@(HoleProv _) = p tidyCos :: TidyEnv -> [Coercion] -> [Coercion] tidyCos env = map (tidyCo env) @@ -2828,26 +3362,28 @@ typeSize (LitTy {}) = 1 typeSize (TyVarTy {}) = 1 typeSize (AppTy t1 t2) = typeSize t1 + typeSize t2 typeSize (FunTy t1 t2) = typeSize t1 + typeSize t2 -typeSize (ForAllTy (TvBndr tv _) t) = typeSize (tyVarKind tv) + typeSize t +typeSize (ForAllTy (Bndr tv _) t) = typeSize (varType tv) + typeSize t typeSize (TyConApp _ ts) = 1 + sum (map typeSize ts) typeSize (CastTy ty co) = typeSize ty + coercionSize co typeSize (CoercionTy co) = coercionSize co coercionSize :: Coercion -> Int -coercionSize (Refl _ ty) = typeSize ty +coercionSize (Refl ty) = typeSize ty +coercionSize (GRefl _ ty MRefl) = typeSize ty +coercionSize (GRefl _ ty (MCo co)) = 1 + typeSize ty + coercionSize co coercionSize (TyConAppCo _ _ args) = 1 + sum (map coercionSize args) coercionSize (AppCo co arg) = coercionSize co + coercionSize arg coercionSize (ForAllCo _ h co) = 1 + coercionSize co + coercionSize h coercionSize (FunCo _ co1 co2) = 1 + coercionSize co1 + coercionSize co2 coercionSize (CoVarCo _) = 1 +coercionSize (HoleCo _) = 1 coercionSize (AxiomInstCo _ _ args) = 1 + sum (map coercionSize args) coercionSize (UnivCo p _ t1 t2) = 1 + provSize p + typeSize t1 + typeSize t2 coercionSize (SymCo co) = 1 + coercionSize co coercionSize (TransCo co1 co2) = 1 + coercionSize co1 + coercionSize co2 -coercionSize (NthCo _ co) = 1 + coercionSize co +coercionSize (NthCo _ _ co) = 1 + coercionSize co coercionSize (LRCo _ co) = 1 + coercionSize co coercionSize (InstCo co arg) = 1 + coercionSize co + coercionSize arg -coercionSize (CoherenceCo c1 c2) = 1 + coercionSize c1 + coercionSize c2 coercionSize (KindCo co) = 1 + coercionSize co coercionSize (SubCo co) = 1 + coercionSize co coercionSize (AxiomRuleCo _ cs) = 1 + sum (map coercionSize cs) @@ -2857,4 +3393,3 @@ provSize UnsafeCoerceProv = 1 provSize (PhantomProv co) = 1 + coercionSize co provSize (ProofIrrelProv co) = 1 + coercionSize co provSize (PluginProv _) = 1 -provSize (HoleProv h) = pprPanic "provSize hits a hole" (ppr h) diff --git a/compiler/types/TyCoRep.hs-boot b/compiler/types/TyCoRep.hs-boot index 8dcbd10744..5af8c1d57f 100644 --- a/compiler/types/TyCoRep.hs-boot +++ b/compiler/types/TyCoRep.hs-boot @@ -1,5 +1,7 @@ module TyCoRep where +import GhcPrelude + import Outputable ( SDoc ) import Data.Data ( Data ) @@ -9,15 +11,19 @@ data Coercion data UnivCoProvenance data TCvSubst data TyLit -data TyBinder +data TyCoBinder +data MCoercion type PredType = Type type Kind = Type type ThetaType = [PredType] +type CoercionN = Coercion +type MCoercionN = MCoercion pprKind :: Kind -> SDoc pprType :: Type -> SDoc +isRuntimeRepTy :: Type -> Bool + instance Data Type -- To support Data instances in CoAxiom - diff --git a/compiler/types/TyCon.hs b/compiler/types/TyCon.hs index 1be318d96a..0bbd8c9e0e 100644 --- a/compiler/types/TyCon.hs +++ b/compiler/types/TyCon.hs @@ -10,16 +10,17 @@ The @TyCon@ datatype module TyCon( -- * Main TyCon data types - TyCon, AlgTyConRhs(..), visibleDataCons, + TyCon, + AlgTyConRhs(..), visibleDataCons, AlgTyConFlav(..), isNoParent, FamTyConFlav(..), Role(..), Injectivity(..), RuntimeRepInfo(..), TyConFlavour(..), -- * TyConBinder - TyConBinder, TyConBndrVis(..), + TyConBinder, TyConBndrVis(..), TyConTyCoBinder, mkNamedTyConBinder, mkNamedTyConBinders, mkAnonTyConBinder, mkAnonTyConBinders, - tyConBinderArgFlag, isNamedTyConBinder, + tyConBinderArgFlag, tyConBndrVisArgFlag, isNamedTyConBinder, isVisibleTyConBinder, isInvisibleTyConBinder, -- ** Field labels @@ -34,6 +35,7 @@ module TyCon( mkLiftedPrimTyCon, mkTupleTyCon, mkSumTyCon, + mkDataTyConRhs, mkSynonymTyCon, mkFamilyTyCon, mkPromotedDataCon, @@ -59,7 +61,7 @@ module TyCon( isFamilyTyCon, isOpenFamilyTyCon, isTypeFamilyTyCon, isDataFamilyTyCon, isOpenTypeFamilyTyCon, isClosedSynFamilyTyConWithAxiom_maybe, - familyTyConInjectivityInfo, + tyConInjectivityInfo, isBuiltInSynFamTyCon_maybe, isUnliftedTyCon, isGadtSyntaxTyCon, isInjectiveTyCon, isGenerativeTyCon, isGenInjAlgRhs, @@ -73,7 +75,7 @@ module TyCon( tyConSkolem, tyConKind, tyConUnique, - tyConTyVars, + tyConTyVars, tyConVisibleTyVars, tyConCType, tyConCType_maybe, tyConDataCons, tyConDataCons_maybe, tyConSingleDataCon_maybe, tyConSingleDataCon, @@ -94,8 +96,9 @@ module TyCon( newTyConDataCon_maybe, algTcFields, tyConRuntimeRepInfo, - tyConBinders, tyConResKind, - tcTyConScopedTyVars, + tyConBinders, tyConResKind, tyConTyVarBinders, + tcTyConScopedTyVars, tcTyConUserTyVars, + mkTyConTagMap, -- ** Manipulating TyCons expandSynTyCon_maybe, @@ -114,22 +117,26 @@ module TyCon( -- * Primitive representations of Types PrimRep(..), PrimElemRep(..), isVoidRep, isGcPtrRep, - primRepSizeW, primElemRepSizeB, + primRepSizeB, + primElemRepSizeB, primRepIsFloat, -- * Recursion breaking - RecTcChecker, initRecTc, checkRecTc + RecTcChecker, initRecTc, defaultRecTcMaxBound, + setRecTcMaxBound, checkRecTc ) where #include "HsVersions.h" +import GhcPrelude + import {-# SOURCE #-} TyCoRep ( Kind, Type, PredType, pprType ) import {-# SOURCE #-} TysWiredIn ( runtimeRepTyCon, constraintKind , vecCountTyCon, vecElemTyCon, liftedTypeKind , mkFunKind, mkForAllKind ) -import {-# SOURCE #-} DataCon ( DataCon, dataConExTyVars, dataConFieldLabels - , dataConTyCon ) +import {-# SOURCE #-} DataCon ( DataCon, dataConExTyCoVars, dataConFieldLabels + , dataConTyCon, dataConFullSig ) import Binary import Var @@ -147,9 +154,10 @@ import FastStringEnv import FieldLabel import Constants import Util -import Unique( tyConRepNameUnique, dataConRepNameUnique ) +import Unique( tyConRepNameUnique, dataConTyRepNameUnique ) import UniqSet import Module +import {-# SOURCE #-} DataCon import qualified Data.Data as Data @@ -222,7 +230,10 @@ See also Note [Wrappers for data instance tycons] in MkId.hs DataFamInstTyCon T [Int] ax_ti * The axiom ax_ti may be eta-reduced; see - Note [Eta reduction for data family axioms] in TcInstDcls + Note [Eta reduction for data family axioms] in FamInstEnv + +* Data family instances may have a different arity than the data family. + See Note [Arity of data families] in FamInstEnv * The data constructor T2 has a wrapper (which is what the source-level "T2" invokes): @@ -238,7 +249,7 @@ See also Note [Wrappers for data instance tycons] in MkId.hs Here's the FC version of the above declaration: - data R:TPair a where + data R:TPair a b where X1 :: R:TPair Int Bool X2 :: a -> b -> R:TPair a b axiom ax_pr :: T (a,b) ~R R:TPair a b @@ -256,7 +267,7 @@ See also Note [Wrappers for data instance tycons] in MkId.hs DataFamInstTyCon T [(a,b)] ax_pr * Notice that T is NOT translated to a FC type function; it just - becomes a "data type" with no constructors, which can be coerced inot + becomes a "data type" with no constructors, which can be coerced into R:TInt, R:TPair by the axioms. These axioms axioms come into play when (and *only* when) you - use a data constructor @@ -302,7 +313,7 @@ parent class. However there is an important sharing relationship between * the tyConTyVars of the parent Class - * the tyConTyvars of the associated TyCon + * the tyConTyVars of the associated TyCon class C a b where data T p a @@ -376,48 +387,64 @@ See also: ************************************************************************ * * - TyConBinder + TyConBinder, TyConTyCoBinder * * ************************************************************************ -} -type TyConBinder = TyVarBndr TyVar TyConBndrVis +type TyConBinder = VarBndr TyVar TyConBndrVis + +-- In the whole definition of @data TyCon@, only @PromotedDataCon@ will really +-- contain CoVar. +type TyConTyCoBinder = VarBndr TyCoVar TyConBndrVis data TyConBndrVis = NamedTCB ArgFlag | AnonTCB +instance Outputable TyConBndrVis where + ppr (NamedTCB flag) = text "NamedTCB" <+> ppr flag + ppr AnonTCB = text "AnonTCB" + mkAnonTyConBinder :: TyVar -> TyConBinder -mkAnonTyConBinder tv = TvBndr tv AnonTCB +mkAnonTyConBinder tv = ASSERT( isTyVar tv) + Bndr tv AnonTCB mkAnonTyConBinders :: [TyVar] -> [TyConBinder] mkAnonTyConBinders tvs = map mkAnonTyConBinder tvs mkNamedTyConBinder :: ArgFlag -> TyVar -> TyConBinder -- The odd argument order supports currying -mkNamedTyConBinder vis tv = TvBndr tv (NamedTCB vis) +mkNamedTyConBinder vis tv = ASSERT( isTyVar tv ) + Bndr tv (NamedTCB vis) mkNamedTyConBinders :: ArgFlag -> [TyVar] -> [TyConBinder] -- The odd argument order supports currying mkNamedTyConBinders vis tvs = map (mkNamedTyConBinder vis) tvs tyConBinderArgFlag :: TyConBinder -> ArgFlag -tyConBinderArgFlag (TvBndr _ (NamedTCB vis)) = vis -tyConBinderArgFlag (TvBndr _ AnonTCB) = Required +tyConBinderArgFlag (Bndr _ vis) = tyConBndrVisArgFlag vis + +tyConBndrVisArgFlag :: TyConBndrVis -> ArgFlag +tyConBndrVisArgFlag (NamedTCB vis) = vis +tyConBndrVisArgFlag AnonTCB = Required isNamedTyConBinder :: TyConBinder -> Bool -- Identifies kind variables -- E.g. data T k (a:k) = blah -- Here 'k' is a NamedTCB, a variable used in the kind of other binders -isNamedTyConBinder (TvBndr _ (NamedTCB {})) = True -isNamedTyConBinder _ = False +isNamedTyConBinder (Bndr _ (NamedTCB {})) = True +isNamedTyConBinder _ = False -isVisibleTyConBinder :: TyVarBndr tv TyConBndrVis -> Bool +isVisibleTyConBinder :: VarBndr tv TyConBndrVis -> Bool -- Works for IfaceTyConBinder too -isVisibleTyConBinder (TvBndr _ (NamedTCB vis)) = isVisibleArgFlag vis -isVisibleTyConBinder (TvBndr _ AnonTCB) = True +isVisibleTyConBinder (Bndr _ tcb_vis) = isVisibleTcbVis tcb_vis + +isVisibleTcbVis :: TyConBndrVis -> Bool +isVisibleTcbVis (NamedTCB vis) = isVisibleArgFlag vis +isVisibleTcbVis AnonTCB = True -isInvisibleTyConBinder :: TyVarBndr tv TyConBndrVis -> Bool +isInvisibleTyConBinder :: VarBndr tv TyConBndrVis -> Bool -- Works for IfaceTyConBinder too isInvisibleTyConBinder tcb = not (isVisibleTyConBinder tcb) @@ -425,41 +452,116 @@ mkTyConKind :: [TyConBinder] -> Kind -> Kind mkTyConKind bndrs res_kind = foldr mk res_kind bndrs where mk :: TyConBinder -> Kind -> Kind - mk (TvBndr tv AnonTCB) k = mkFunKind (tyVarKind tv) k - mk (TvBndr tv (NamedTCB vis)) k = mkForAllKind tv vis k + mk (Bndr tv AnonTCB) k = mkFunKind (varType tv) k + mk (Bndr tv (NamedTCB vis)) k = mkForAllKind tv vis k + +tyConTyVarBinders :: [TyConBinder] -- From the TyCon + -> [TyVarBinder] -- Suitable for the foralls of a term function +-- See Note [Building TyVarBinders from TyConBinders] +tyConTyVarBinders tc_bndrs + = map mk_binder tc_bndrs + where + mk_binder (Bndr tv tc_vis) = mkTyVarBinder vis tv + where + vis = case tc_vis of + AnonTCB -> Specified + NamedTCB Required -> Specified + NamedTCB vis -> vis + +-- Returns only tyvars, as covars are always inferred +tyConVisibleTyVars :: TyCon -> [TyVar] +tyConVisibleTyVars tc + = [ tv | Bndr tv vis <- tyConBinders tc + , isVisibleTcbVis vis ] + +{- Note [Building TyVarBinders from TyConBinders] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We sometimes need to build the quantified type of a value from +the TyConBinders of a type or class. For that we need not +TyConBinders but TyVarBinders (used in forall-type) E.g: + + * From data T a = MkT (Maybe a) + we are going to make a data constructor with type + MkT :: forall a. Maybe a -> T a + See the TyCoVarBinders passed to buildDataCon + + * From class C a where { op :: a -> Maybe a } + we are going to make a default method + $dmop :: forall a. C a => a -> Maybe a + See the TyCoVarBinders passed to mkSigmaTy in mkDefaultMethodType + +Both of these are user-callable. (NB: default methods are not callable +directly by the user but rather via the code generated by 'deriving', +which uses visible type application; see mkDefMethBind.) + +Since they are user-callable we must get their type-argument visibility +information right; and that info is in the TyConBinders. +Here is an example: + + data App a b = MkApp (a b) -- App :: forall {k}. (k->*) -> k -> * + +The TyCon has + + tyConTyBinders = [ Named (Bndr (k :: *) Inferred), Anon (k->*), Anon k ] + +The TyConBinders for App line up with App's kind, given above. + +But the DataCon MkApp has the type + MkApp :: forall {k} (a:k->*) (b:k). a b -> App k a b + +That is, its TyCoVarBinders should be + + dataConUnivTyVarBinders = [ Bndr (k:*) Inferred + , Bndr (a:k->*) Specified + , Bndr (b:k) Specified ] + +So tyConTyVarBinders converts TyCon's TyConBinders into TyVarBinders: + - variable names from the TyConBinders + - but changing Anon/Required to Specified + +The last part about Required->Specified comes from this: + data T k (a:k) b = MkT (a b) +Here k is Required in T's kind, but we don't have Required binders in +the TyCoBinders for a term (see Note [No Required TyCoBinder in terms] +in TyCoRep), so we change it to Specified when making MkT's TyCoBinders +-} + {- Note [The binders/kind/arity fields of a TyCon] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All TyCons have this group of fields - tyConBinders :: [TyConBinder] - tyConResKind :: Kind - tyConTyVars :: [TyVar] -- Cached = binderVars tyConBinders - tyConKind :: Kind -- Cached = mkTyConKind tyConBinders tyConResKind - tyConArity :: Arity -- Cached = length tyConBinders + tyConBinders :: [TyConBinder/TyConTyCoBinder] + tyConResKind :: Kind + tyConTyVars :: [TyVar] -- Cached = binderVars tyConBinders + -- NB: Currently (Aug 2018), TyCons that own this + -- field really only contain TyVars. So it is + -- [TyVar] instead of [TyCoVar]. + tyConKind :: Kind -- Cached = mkTyConKind tyConBinders tyConResKind + tyConArity :: Arity -- Cached = length tyConBinders They fit together like so: -* tyConBinders gives the telescope of type variables on the LHS of the +* tyConBinders gives the telescope of type/coercion variables on the LHS of the type declaration. For example: type App a (b :: k) = a b - tyConBinders = [ TvBndr (k::*) (NamedTCB Inferred) - , TvBndr (a:k->*) AnonTCB - , TvBndr (b:k) AnonTCB ] + tyConBinders = [ Bndr (k::*) (NamedTCB Inferred) + , Bndr (a:k->*) AnonTCB + , Bndr (b:k) AnonTCB ] Note that that are three binders here, including the kind variable k. - See Note [TyBinders and ArgFlags] in TyCoRep for what - the visibility flag means. +- See Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] in TyCoRep + for what the visibility flag means. -* Each TyConBinder tyConBinders has a TyVar, and that TyVar may - scope over some other part of the TyCon's definition. Eg - type T a = a->a +* Each TyConBinder tyConBinders has a TyVar (sometimes it is TyCoVar), and + that TyVar may scope over some other part of the TyCon's definition. Eg + type T a = a -> a we have - tyConBinders = [ TvBndr (a:*) AnonTCB ] - synTcRhs = a->a + tyConBinders = [ Bndr (a:*) AnonTCB ] + synTcRhs = a -> a So the 'a' scopes over the synTcRhs * From the tyConBinders and tyConResKind we can get the tyConKind @@ -477,11 +579,11 @@ They fit together like so: So it's just (length tyConBinders) -} -instance Outputable tv => Outputable (TyVarBndr tv TyConBndrVis) where - ppr (TvBndr v AnonTCB) = ppr v - ppr (TvBndr v (NamedTCB Required)) = ppr v - ppr (TvBndr v (NamedTCB Specified)) = char '@' <> ppr v - ppr (TvBndr v (NamedTCB Inferred)) = braces (ppr v) +instance Outputable tv => Outputable (VarBndr tv TyConBndrVis) where + ppr (Bndr v AnonTCB) = text "anon" <+> parens (ppr v) + ppr (Bndr v (NamedTCB Required)) = text "req" <+> parens (ppr v) + ppr (Bndr v (NamedTCB Specified)) = text "spec" <+> parens (ppr v) + ppr (Bndr v (NamedTCB Inferred)) = text "inf" <+> parens (ppr v) instance Binary TyConBndrVis where put_ bh AnonTCB = putByte bh 0 @@ -710,7 +812,7 @@ data TyCon tyConName :: Name, -- ^ Same Name as the data constructor -- See Note [The binders/kind/arity fields of a TyCon] - tyConBinders :: [TyConBinder], -- ^ Full binders + tyConBinders :: [TyConTyCoBinder], -- ^ Full binders tyConResKind :: Kind, -- ^ Result kind tyConKind :: Kind, -- ^ Kind of this TyCon tyConArity :: Arity, -- ^ Arity @@ -721,7 +823,8 @@ data TyCon promDcRepInfo :: RuntimeRepInfo -- ^ See comments with 'RuntimeRepInfo' } - -- | These exist only during a recursive type/class type-checking knot. + -- | These exist only during type-checking. See Note [How TcTyCons work] + -- in TcTyClsDecls | TcTyCon { tyConUnique :: Unique, tyConName :: Name, @@ -733,8 +836,12 @@ data TyCon tyConKind :: Kind, -- ^ Kind of this TyCon tyConArity :: Arity, -- ^ Arity - tcTyConScopedTyVars :: [TyVar], -- ^ Scoped tyvars over the - -- tycon's body. See Note [TcTyCon] + tcTyConScopedTyVars :: [(Name,TyVar)], + -- ^ Scoped tyvars over the tycon's body + -- See Note [How TcTyCons work] in TcTyClsDecls + -- Order does *not* matter. + tcTyConUserTyVars :: SDoc, -- ^ Original, user-written tycon tyvars + tcTyConFlavour :: TyConFlavour -- ^ What sort of 'TyCon' this represents. } @@ -756,8 +863,9 @@ data AlgTyConRhs -- user declares the type to have no constructors -- -- INVARIANT: Kept in order of increasing 'DataCon' - -- tag (see the tag assignment in DataCon.mkDataCon) - + -- tag (see the tag assignment in mkTyConTagMap) + data_cons_size :: Int, + -- ^ Cached value: length data_cons is_enum :: Bool -- ^ Cached value: is this an enumeration type? -- See Note [Enumeration types] } @@ -768,8 +876,10 @@ data AlgTyConRhs -- tuple? } + -- | An unboxed sum type. | SumTyCon { - data_cons :: [DataCon] + data_cons :: [DataCon], + data_cons_size :: Int -- ^ Cached value: length data_cons } -- | Information about those 'TyCon's derived from a @newtype@ declaration @@ -803,6 +913,23 @@ data AlgTyConRhs -- again check Trac #1072. } +mkSumTyConRhs :: [DataCon] -> AlgTyConRhs +mkSumTyConRhs data_cons = SumTyCon data_cons (length data_cons) + +mkDataTyConRhs :: [DataCon] -> AlgTyConRhs +mkDataTyConRhs cons + = DataTyCon { + data_cons = cons, + data_cons_size = length cons, + is_enum = not (null cons) && all is_enum_con cons + -- See Note [Enumeration types] in TyCon + } + where + is_enum_con con + | (_univ_tvs, ex_tvs, eq_spec, theta, arg_tys, _res) + <- dataConFullSig con + = null ex_tvs && null eq_spec && null theta && null arg_tys + -- | Some promoted datacons signify extra info relevant to GHC. For example, -- the @IntRep@ constructor of @RuntimeRep@ corresponds to the 'IntRep' -- constructor of 'PrimRep'. This data structure allows us to store this @@ -874,7 +1001,8 @@ data AlgTyConFlav -- use the tyConTyVars of this TyCon TyCon -- The family TyCon [Type] -- Argument types (mentions the tyConTyVars of this TyCon) - -- Match in length the tyConTyVars of the family TyCon + -- No shorter in length than the tyConTyVars of the family TyCon + -- How could it be longer? See [Arity of data families] in FamInstEnv -- E.g. data instance T [a] = ... -- gives a representation tycon: @@ -895,7 +1023,7 @@ okParent :: Name -> AlgTyConFlav -> Bool okParent _ (VanillaAlgTyCon {}) = True okParent _ (UnboxedAlgTyCon {}) = True okParent tc_name (ClassTyCon cls _) = tc_name == tyConName (classTyCon cls) -okParent _ (DataFamInstTyCon _ fam_tc tys) = tys `lengthIs` tyConArity fam_tc +okParent _ (DataFamInstTyCon _ fam_tc tys) = tys `lengthAtLeast` tyConArity fam_tc isNoParent :: AlgTyConFlav -> Bool isNoParent (VanillaAlgTyCon {}) = True @@ -1054,51 +1182,8 @@ so the coercion tycon CoT must have kind: T ~ [] and arity: 0 -Note [TcTyCon] -~~~~~~~~~~~~~~ -TcTyCons are used for two distinct purposes - -1. When recovering from a type error in a type declaration, - we want to put the erroneous TyCon in the environment in a - way that won't lead to more errors. We use a TcTyCon for this; - see makeRecoveryTyCon. - -2. When checking a type/class declaration (in module TcTyClsDecls), we come - upon knowledge of the eventual tycon in bits and pieces. First, we use - getInitialKinds to look over the user-provided kind signature of a tycon - (including, for example, the number of parameters written to the tycon) - to get an initial shape of the tycon's kind. Then, using these initial - kinds, we kind-check the body of the tycon (class methods, data constructors, - etc.), filling in the metavariables in the tycon's initial kind. - We then generalize to get the tycon's final, fixed kind. Finally, once - this has happened for all tycons in a mutually recursive group, we - can desugar the lot. - - For convenience, we store partially-known tycons in TcTyCons, which - might store meta-variables. These TcTyCons are stored in the local - environment in TcTyClsDecls, until the real full TyCons can be created - during desugaring. A desugared program should never have a TcTyCon. - - A challenging piece in all of this is that we end up taking three separate - passes over every declaration: one in getInitialKind (this pass look only - at the head, not the body), one in kcTyClDecls (to kind-check the body), - and a final one in tcTyClDecls (to desugar). In the latter two passes, - we need to connect the user-written type variables in an LHsQTyVars - with the variables in the tycon's inferred kind. Because the tycon might - not have a CUSK, this matching up is, in general, quite hard to do. - (Look through the git history between Dec 2015 and Apr 2016 for - TcHsType.splitTelescopeTvs!) Instead of trying, we just store the list - of type variables to bring into scope in the later passes when we create - a TcTyCon in getInitialKinds. Much easier this way! These tyvars are - brought into scope in kcTyClTyVars and tcTyClTyVars, both in TcHsType. - - It is important that the scoped type variables not be zonked, as some - scoped type variables come into existence as SigTvs. If we zonk, the - Unique will change and the user-written occurrences won't match up with - what we expect. - - In a TcTyCon, everything is zonked (except the scoped vars) after - the kind-checking pass. +This eta-reduction is implemented in BuildTyCl.mkNewTyConRhs. + ************************************************************************ * * @@ -1121,7 +1206,10 @@ tyConRepName_maybe (AlgTyCon { algTcParent = parent }) | UnboxedAlgTyCon rep_nm <- parent = rep_nm tyConRepName_maybe (FamilyTyCon { famTcFlav = DataFamilyTyCon rep_nm }) = Just rep_nm -tyConRepName_maybe (PromotedDataCon { tcRepName = rep_nm }) +tyConRepName_maybe (PromotedDataCon { dataCon = dc, tcRepName = rep_nm }) + | isUnboxedSumCon dc -- see #13276 + = Nothing + | otherwise = Just rep_nm tyConRepName_maybe _ = Nothing @@ -1136,7 +1224,7 @@ mkPrelTyConRepName tc_name -- Prelude tc_name is always External, name_mod = nameModule tc_name name_uniq = nameUnique tc_name rep_uniq | isTcOcc name_occ = tyConRepNameUnique name_uniq - | otherwise = dataConRepNameUnique name_uniq + | otherwise = dataConTyRepNameUnique name_uniq (rep_mod, rep_occ) = tyConRepModOcc name_mod name_occ -- | The name (and defining module) for the Typeable representation (TyCon) of a @@ -1259,19 +1347,25 @@ isGcPtrRep LiftedRep = True isGcPtrRep UnliftedRep = True isGcPtrRep _ = False --- | Find the size of a 'PrimRep', in words -primRepSizeW :: DynFlags -> PrimRep -> Int -primRepSizeW _ IntRep = 1 -primRepSizeW _ WordRep = 1 -primRepSizeW dflags Int64Rep = wORD64_SIZE `quot` wORD_SIZE dflags -primRepSizeW dflags Word64Rep = wORD64_SIZE `quot` wORD_SIZE dflags -primRepSizeW _ FloatRep = 1 -- NB. might not take a full word -primRepSizeW dflags DoubleRep = dOUBLE_SIZE dflags `quot` wORD_SIZE dflags -primRepSizeW _ AddrRep = 1 -primRepSizeW _ LiftedRep = 1 -primRepSizeW _ UnliftedRep = 1 -primRepSizeW _ VoidRep = 0 -primRepSizeW dflags (VecRep len rep) = len * primElemRepSizeB rep `quot` wORD_SIZE dflags +-- | The size of a 'PrimRep' in bytes. +-- +-- This applies also when used in a constructor, where we allow packing the +-- fields. For instance, in @data Foo = Foo Float# Float#@ the two fields will +-- take only 8 bytes, which for 64-bit arch will be equal to 1 word. +-- See also mkVirtHeapOffsetsWithPadding for details of how data fields are +-- layed out. +primRepSizeB :: DynFlags -> PrimRep -> Int +primRepSizeB dflags IntRep = wORD_SIZE dflags +primRepSizeB dflags WordRep = wORD_SIZE dflags +primRepSizeB _ Int64Rep = wORD64_SIZE +primRepSizeB _ Word64Rep = wORD64_SIZE +primRepSizeB _ FloatRep = fLOAT_SIZE +primRepSizeB dflags DoubleRep = dOUBLE_SIZE dflags +primRepSizeB dflags AddrRep = wORD_SIZE dflags +primRepSizeB dflags LiftedRep = wORD_SIZE dflags +primRepSizeB dflags UnliftedRep = wORD_SIZE dflags +primRepSizeB _ VoidRep = 0 +primRepSizeB _ (VecRep len rep) = len * primElemRepSizeB rep primElemRepSizeB :: PrimElemRep -> Int primElemRepSizeB Int8ElemRep = 1 @@ -1341,7 +1435,7 @@ So we compromise, and move their Kind calculation to the call site. -} -- | Given the name of the function type constructor and it's kind, create the --- corresponding 'TyCon'. It is recomended to use 'TyCoRep.funTyCon' if you want +-- corresponding 'TyCon'. It is recommended to use 'TyCoRep.funTyCon' if you want -- this functionality mkFunTyCon :: Name -> [TyConBinder] -> Name -> TyCon mkFunTyCon name binders rep_nm @@ -1446,24 +1540,27 @@ mkSumTyCon name binders res_kind arity tyvars cons parent tyConCType = Nothing, algTcGadtSyntax = False, algTcStupidTheta = [], - algTcRhs = SumTyCon { data_cons = cons }, + algTcRhs = mkSumTyConRhs cons, algTcFields = emptyDFsEnv, algTcParent = parent } --- | Makes a tycon suitable for use during type-checking. --- The only real need for this is for printing error messages during --- a recursive type/class type-checking knot. It has a kind because --- TcErrors sometimes calls typeKind. +-- | Makes a tycon suitable for use during type-checking. It stores +-- a variety of details about the definition of the TyCon, but no +-- right-hand side. It lives only during the type-checking of a +-- mutually-recursive group of tycons; it is then zonked to a proper +-- TyCon in zonkTcTyCon. -- See also Note [Kind checking recursive type and class declarations] -- in TcTyClsDecls. mkTcTyCon :: Name + -> SDoc -- ^ user-written tycon tyvars -> [TyConBinder] -> Kind -- ^ /result/ kind only - -> [TyVar] -- ^ Scoped type variables, see Note [TcTyCon] + -> [(Name,TcTyVar)] -- ^ Scoped type variables; + -- see Note [How TcTyCons work] in TcTyClsDecls -> TyConFlavour -- ^ What sort of 'TyCon' this represents -> TyCon -mkTcTyCon name binders res_kind scoped_tvs flav +mkTcTyCon name tyvars binders res_kind scoped_tvs flav = TcTyCon { tyConUnique = getUnique name , tyConName = name , tyConTyVars = binderVars binders @@ -1472,7 +1569,8 @@ mkTcTyCon name binders res_kind scoped_tvs flav , tyConKind = mkTyConKind binders res_kind , tyConArity = length binders , tcTyConScopedTyVars = scoped_tvs - , tcTyConFlavour = flav } + , tcTyConFlavour = flav + , tcTyConUserTyVars = tyvars } -- | Create an unlifted primitive 'TyCon', such as @Int#@. mkPrimTyCon :: Name -> [TyConBinder] @@ -1560,7 +1658,7 @@ mkFamilyTyCon name binders res_kind resVar flav parent inj -- as the data constructor itself; when we pretty-print -- the TyCon we add a quote; see the Outputable TyCon instance mkPromotedDataCon :: DataCon -> Name -> TyConRepName - -> [TyConBinder] -> Kind -> [Role] + -> [TyConTyCoBinder] -> Kind -> [Role] -> RuntimeRepInfo -> TyCon mkPromotedDataCon con name rep_name binders res_kind roles rep_info = PromotedDataCon { @@ -1585,11 +1683,11 @@ isAbstractTyCon :: TyCon -> Bool isAbstractTyCon (AlgTyCon { algTcRhs = AbstractTyCon }) = True isAbstractTyCon _ = False --- | Make an fake, recovery 'TyCon' from an existing one. +-- | Make a fake, recovery 'TyCon' from an existing one. -- Used when recovering from errors makeRecoveryTyCon :: TyCon -> TyCon makeRecoveryTyCon tc - = mkTcTyCon (tyConName tc) + = mkTcTyCon (tyConName tc) empty (tyConBinders tc) (tyConResKind tc) [{- no scoped vars -}] (tyConFlavour tc) @@ -1666,7 +1764,7 @@ isInjectiveTyCon (PrimTyCon {}) _ = True isInjectiveTyCon (PromotedDataCon {}) _ = True isInjectiveTyCon (TcTyCon {}) _ = True -- Reply True for TcTyCon to minimise knock on type errors - -- See Note [TcTyCon] item (1) + -- See Note [How TcTyCons work] item (1) in TcTyClsDecls -- | 'isGenerativeTyCon' is true of 'TyCon's for which this property holds -- (where X is the role passed in): @@ -1692,8 +1790,9 @@ isNewTyCon :: TyCon -> Bool isNewTyCon (AlgTyCon {algTcRhs = NewTyCon {}}) = True isNewTyCon _ = False --- | Take a 'TyCon' apart into the 'TyVar's it scopes over, the 'Type' it expands --- into, and (possibly) a coercion from the representation type to the @newtype@. +-- | Take a 'TyCon' apart into the 'TyVar's it scopes over, the 'Type' it +-- expands into, and (possibly) a coercion from the representation type to the +-- @newtype@. -- Returns @Nothing@ if this is not possible. unwrapNewTyCon_maybe :: TyCon -> Maybe ([TyVar], Type, CoAxiom Unbranched) unwrapNewTyCon_maybe (AlgTyCon { tyConTyVars = tvs, @@ -1716,7 +1815,7 @@ isProductTyCon tc@(AlgTyCon {}) = case algTcRhs tc of TupleTyCon {} -> True DataTyCon{ data_cons = [data_con] } - -> null (dataConExTyVars data_con) + -> null (dataConExTyCoVars data_con) NewTyCon {} -> True _ -> False isProductTyCon _ = False @@ -1728,7 +1827,7 @@ isDataProductTyCon_maybe :: TyCon -> Maybe DataCon isDataProductTyCon_maybe (AlgTyCon { algTcRhs = rhs }) = case rhs of DataTyCon { data_cons = [con] } - | null (dataConExTyVars con) -- non-existential + | null (dataConExTyCoVars con) -- non-existential -> Just con TupleTyCon { data_con = con } -> Just con @@ -1740,10 +1839,10 @@ isDataSumTyCon_maybe (AlgTyCon { algTcRhs = rhs }) = case rhs of DataTyCon { data_cons = cons } | cons `lengthExceeds` 1 - , all (null . dataConExTyVars) cons -- FIXME(osa): Why do we need this? + , all (null . dataConExTyCoVars) cons -- FIXME(osa): Why do we need this? -> Just cons SumTyCon { data_cons = cons } - | all (null . dataConExTyVars) cons -- FIXME(osa): Why do we need this? + | all (null . dataConExTyCoVars) cons -- FIXME(osa): Why do we need this? -> Just cons _ -> Nothing isDataSumTyCon_maybe _ = Nothing @@ -1855,11 +1954,17 @@ isClosedSynFamilyTyConWithAxiom_maybe (FamilyTyCon {famTcFlav = ClosedSynFamilyTyCon mb}) = mb isClosedSynFamilyTyConWithAxiom_maybe _ = Nothing --- | Try to read the injectivity information from a FamilyTyCon. --- For every other TyCon this function panics. -familyTyConInjectivityInfo :: TyCon -> Injectivity -familyTyConInjectivityInfo (FamilyTyCon { famTcInj = inj }) = inj -familyTyConInjectivityInfo _ = panic "familyTyConInjectivityInfo" +-- | @'tyConInjectivityInfo' tc@ returns @'Injective' is@ is @tc@ is an +-- injective tycon (where @is@ states for which 'tyConBinders' @tc@ is +-- injective), or 'NotInjective' otherwise. +tyConInjectivityInfo :: TyCon -> Injectivity +tyConInjectivityInfo tc + | FamilyTyCon { famTcInj = inj } <- tc + = inj + | isInjectiveTyCon tc Nominal + = Injective (replicate (tyConArity tc) True) + | otherwise + = NotInjective isBuiltInSynFamTyCon_maybe :: TyCon -> Maybe BuiltInSynFamily isBuiltInSynFamTyCon_maybe @@ -1944,18 +2049,14 @@ isKindTyCon tc = getUnique tc `elementOfUniqSet` kindTyConKeys -- -XDataKinds. kindTyConKeys :: UniqSet Unique kindTyConKeys = unionManyUniqSets - ( mkUniqSet [ liftedTypeKindTyConKey, starKindTyConKey, unicodeStarKindTyConKey - , constraintKindTyConKey, tYPETyConKey ] + ( mkUniqSet [ liftedTypeKindTyConKey, constraintKindTyConKey, tYPETyConKey ] : map (mkUniqSet . tycon_with_datacons) [ runtimeRepTyCon , vecCountTyCon, vecElemTyCon ] ) where tycon_with_datacons tc = getUnique tc : map getUnique (tyConDataCons tc) isLiftedTypeKindTyConName :: Name -> Bool -isLiftedTypeKindTyConName - = (`hasKey` liftedTypeKindTyConKey) <||> - (`hasKey` starKindTyConKey) <||> - (`hasKey` unicodeStarKindTyConKey) +isLiftedTypeKindTyConName = (`hasKey` liftedTypeKindTyConKey) -- | Identifies implicit tycons that, in particular, do not go into interface -- files (because they are implicitly reconstructed when the interface is @@ -2038,6 +2139,10 @@ expandSynTyCon_maybe tc tys -- | Check if the tycon actually refers to a proper `data` or `newtype` -- with user defined constructors rather than one from a class or other -- construction. + +-- NB: This is only used in TcRnExports.checkPatSynParent to determine if an +-- exported tycon can have a pattern synonym bundled with it, e.g., +-- module Foo (TyCon(.., PatSyn)) where isTyConWithSrcDataCons :: TyCon -> Bool isTyConWithSrcDataCons (AlgTyCon { algTcRhs = rhs, algTcParent = parent }) = case rhs of @@ -2047,6 +2152,8 @@ isTyConWithSrcDataCons (AlgTyCon { algTcRhs = rhs, algTcParent = parent }) = _ -> False where isSrcParent = isNoParent parent +isTyConWithSrcDataCons (FamilyTyCon { famTcFlav = DataFamilyTyCon {} }) + = True -- #14058 isTyConWithSrcDataCons _ = False @@ -2105,10 +2212,10 @@ tyConSingleAlgDataCon_maybe _ = Nothing tyConFamilySize :: TyCon -> Int tyConFamilySize tc@(AlgTyCon { algTcRhs = rhs }) = case rhs of - DataTyCon { data_cons = cons } -> length cons + DataTyCon { data_cons_size = size } -> size NewTyCon {} -> 1 TupleTyCon {} -> 1 - SumTyCon { data_cons = cons } -> length cons + SumTyCon { data_cons_size = size } -> size _ -> pprPanic "tyConFamilySize 1" (ppr tc) tyConFamilySize tc = pprPanic "tyConFamilySize 2" (ppr tc) @@ -2252,6 +2359,28 @@ tyConRuntimeRepInfo _ = NoRRI -- could panic in that second case. But Douglas Adams told me not to. {- +Note [Constructor tag allocation] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When typechecking we need to allocate constructor tags to constructors. +They are allocated based on the position in the data_cons field of TyCon, +with the first constructor getting fIRST_TAG. + +We used to pay linear cost per constructor, with each constructor looking up +its relative index in the constructor list. That was quadratic and prohibitive +for large data types with more than 10k constructors. + +The current strategy is to build a NameEnv with a mapping from costructor's +Name to ConTag and pass it down to buildDataCon for efficient lookup. + +Relevant ticket: #14657 +-} + +mkTyConTagMap :: TyCon -> NameEnv ConTag +mkTyConTagMap tycon = + mkNameEnv $ map getName (tyConDataCons tycon) `zip` [fIRST_TAG..] + -- See Note [Constructor tag allocation] + +{- ************************************************************************ * * \subsection[TyCon-instances]{Instance declarations for @TyCon@} @@ -2271,7 +2400,11 @@ instance Uniquable TyCon where instance Outputable TyCon where -- At the moment a promoted TyCon has the same Name as its -- corresponding TyCon, so we add the quote to distinguish it here - ppr tc = pprPromotionQuote tc <> ppr (tyConName tc) + ppr tc = pprPromotionQuote tc <> ppr (tyConName tc) <> pp_tc + where + pp_tc = getPprStyle $ \sty -> if ((debugStyle sty || dumpStyle sty) && isTcTyCon tc) + then text "[tc]" + else empty -- | Paints a picture of what a 'TyCon' represents, in broad strokes. -- This is used towards more informative error messages. @@ -2282,8 +2415,8 @@ data TyConFlavour | DataTypeFlavour | NewtypeFlavour | AbstractTypeFlavour - | DataFamilyFlavour - | OpenTypeFamilyFlavour + | DataFamilyFlavour Bool -- True <=> associated + | OpenTypeFamilyFlavour Bool -- True <=> associated | ClosedTypeFamilyFlavour | TypeSynonymFlavour | BuiltInTypeFlavour -- ^ e.g., the @(->)@ 'TyCon'. @@ -2300,8 +2433,10 @@ instance Outputable TyConFlavour where go DataTypeFlavour = "data type" go NewtypeFlavour = "newtype" go AbstractTypeFlavour = "abstract type" - go DataFamilyFlavour = "data family" - go OpenTypeFamilyFlavour = "type family" + go (DataFamilyFlavour True) = "associated data family" + go (DataFamilyFlavour False) = "data family" + go (OpenTypeFamilyFlavour True) = "associated type family" + go (OpenTypeFamilyFlavour False) = "type family" go ClosedTypeFamilyFlavour = "type family" go TypeSynonymFlavour = "type synonym" go BuiltInTypeFlavour = "built-in type" @@ -2317,10 +2452,10 @@ tyConFlavour (AlgTyCon { algTcParent = parent, algTcRhs = rhs }) DataTyCon {} -> DataTypeFlavour NewTyCon {} -> NewtypeFlavour AbstractTyCon {} -> AbstractTypeFlavour -tyConFlavour (FamilyTyCon { famTcFlav = flav }) +tyConFlavour (FamilyTyCon { famTcFlav = flav, famTcParent = parent }) = case flav of - DataFamilyTyCon{} -> DataFamilyFlavour - OpenSynFamilyTyCon -> OpenTypeFamilyFlavour + DataFamilyTyCon{} -> DataFamilyFlavour (isJust parent) + OpenSynFamilyTyCon -> OpenTypeFamilyFlavour (isJust parent) ClosedSynFamilyTyCon{} -> ClosedTypeFamilyFlavour AbstractClosedSynFamilyTyCon -> ClosedTypeFamilyFlavour BuiltInSynFamTyCon{} -> ClosedTypeFamilyFlavour @@ -2335,20 +2470,20 @@ tcFlavourCanBeUnsaturated :: TyConFlavour -> Bool tcFlavourCanBeUnsaturated ClassFlavour = True tcFlavourCanBeUnsaturated DataTypeFlavour = True tcFlavourCanBeUnsaturated NewtypeFlavour = True -tcFlavourCanBeUnsaturated DataFamilyFlavour = True +tcFlavourCanBeUnsaturated DataFamilyFlavour{} = True tcFlavourCanBeUnsaturated TupleFlavour{} = True tcFlavourCanBeUnsaturated SumFlavour = True tcFlavourCanBeUnsaturated AbstractTypeFlavour = True tcFlavourCanBeUnsaturated BuiltInTypeFlavour = True tcFlavourCanBeUnsaturated PromotedDataConFlavour = True tcFlavourCanBeUnsaturated TypeSynonymFlavour = False -tcFlavourCanBeUnsaturated OpenTypeFamilyFlavour = False +tcFlavourCanBeUnsaturated OpenTypeFamilyFlavour{} = False tcFlavourCanBeUnsaturated ClosedTypeFamilyFlavour = False -- | Is this flavour of 'TyCon' an open type family or a data family? tcFlavourIsOpen :: TyConFlavour -> Bool -tcFlavourIsOpen DataFamilyFlavour = True -tcFlavourIsOpen OpenTypeFamilyFlavour = True +tcFlavourIsOpen DataFamilyFlavour{} = True +tcFlavourIsOpen OpenTypeFamilyFlavour{} = True tcFlavourIsOpen ClosedTypeFamilyFlavour = False tcFlavourIsOpen ClassFlavour = False tcFlavourIsOpen DataTypeFlavour = False @@ -2437,10 +2572,20 @@ data RecTcChecker = RC !Int (NameEnv Int) -- The upper bound, and the number of times -- we have encountered each TyCon +-- | Initialise a 'RecTcChecker' with 'defaultRecTcMaxBound'. initRecTc :: RecTcChecker --- Intialise with a fixed max bound of 100 --- We should probably have a flag for this -initRecTc = RC 100 emptyNameEnv +initRecTc = RC defaultRecTcMaxBound emptyNameEnv + +-- | The default upper bound (100) for the number of times a 'RecTcChecker' is +-- allowed to encounter each 'TyCon'. +defaultRecTcMaxBound :: Int +defaultRecTcMaxBound = 100 +-- Should we have a flag for this? + +-- | Change the upper bound for the number of times a 'RecTcChecker' is allowed +-- to encounter each 'TyCon'. +setRecTcMaxBound :: Int -> RecTcChecker -> RecTcChecker +setRecTcMaxBound new_bound (RC _old_bound rec_nts) = RC new_bound rec_nts checkRecTc :: RecTcChecker -> TyCon -> Maybe RecTcChecker -- Nothing => Recursion detected diff --git a/compiler/types/TyCon.hs-boot b/compiler/types/TyCon.hs-boot index d77ed8a172..4db8d0f1c1 100644 --- a/compiler/types/TyCon.hs-boot +++ b/compiler/types/TyCon.hs-boot @@ -1,5 +1,7 @@ module TyCon where +import GhcPrelude + data TyCon isTupleTyCon :: TyCon -> Bool diff --git a/compiler/types/Type.hs b/compiler/types/Type.hs index 8621e6cd52..bda3602815 100644 --- a/compiler/types/Type.hs +++ b/compiler/types/Type.hs @@ -15,11 +15,12 @@ module Type ( -- $representation_types TyThing(..), Type, ArgFlag(..), KindOrType, PredType, ThetaType, - Var, TyVar, isTyVar, TyCoVar, TyBinder, TyVarBinder, + Var, TyVar, isTyVar, TyCoVar, TyCoBinder, TyCoVarBinder, TyVarBinder, + KnotTied, -- ** Constructing and deconstructing types mkTyVarTy, mkTyVarTys, getTyVar, getTyVar_maybe, repGetTyVar_maybe, - getCastedTyVar_maybe, tyVarKind, + getCastedTyVar_maybe, tyVarKind, varType, mkAppTy, mkAppTys, splitAppTy, splitAppTys, repSplitAppTys, splitAppTy_maybe, repSplitAppTy_maybe, tcRepSplitAppTy_maybe, @@ -35,18 +36,22 @@ module Type ( splitListTyConApp_maybe, repSplitTyConApp_maybe, - mkForAllTy, mkForAllTys, mkInvForAllTys, mkSpecForAllTys, - mkVisForAllTys, mkInvForAllTy, - splitForAllTys, splitForAllTyVarBndrs, + mkForAllTy, mkForAllTys, mkTyCoInvForAllTys, mkSpecForAllTys, + mkVisForAllTys, mkTyCoInvForAllTy, + mkInvForAllTy, mkInvForAllTys, + splitForAllTys, splitForAllVarBndrs, splitForAllTy_maybe, splitForAllTy, + splitForAllTy_ty_maybe, splitForAllTy_co_maybe, splitPiTy_maybe, splitPiTy, splitPiTys, - mkPiTy, mkPiTys, mkTyConBindersPreferAnon, + mkTyCoPiTy, mkTyCoPiTys, mkTyConBindersPreferAnon, + mkPiTys, mkLamType, mkLamTypes, piResultTy, piResultTys, applyTysX, dropForAlls, mkNumLitTy, isNumLitTy, mkStrLitTy, isStrLitTy, + isLitTy, getRuntimeRep_maybe, getRuntimeRepFromKind_maybe, @@ -58,7 +63,7 @@ module Type ( stripCoercionTy, splitCoercionType_maybe, splitPiTysInvisible, filterOutInvisibleTypes, - filterOutInvisibleTyVars, partitionInvisibles, + partitionInvisibleTypes, partitionInvisibles, synTyConResKind, modifyJoinResTy, setJoinResTy, @@ -88,15 +93,16 @@ module Type ( -- ** Binders sameVis, - mkTyVarBinder, mkTyVarBinders, + mkTyCoVarBinder, mkTyCoVarBinders, + mkTyVarBinders, mkAnonBinder, - isAnonTyBinder, isNamedTyBinder, - binderVar, binderVars, binderKind, binderArgFlag, + isAnonTyCoBinder, isNamedTyCoBinder, + binderVar, binderVars, binderType, binderArgFlag, + tyCoBinderType, tyCoBinderVar_maybe, tyBinderType, binderRelevantType_maybe, caseBinder, isVisibleArgFlag, isInvisibleArgFlag, isVisibleBinder, isInvisibleBinder, - tyConBindersTyBinders, - mkTyBinderTyConBinder, + tyConBindersTyCoBinders, -- ** Common type constructors funTyCon, @@ -104,13 +110,14 @@ module Type ( -- ** Predicates on types isTyVarTy, isFunTy, isDictTy, isPredTy, isCoercionTy, isCoercionTy_maybe, isCoercionType, isForAllTy, + isForAllTy_ty, isForAllTy_co, isPiTy, isTauTy, isFamFreeTy, isValidJoinPointType, -- (Lifting and boxity) isLiftedType_maybe, isUnliftedType, isUnboxedTupleType, isUnboxedSumType, - isAlgType, isClosedAlgType, isDataFamilyAppType, + isAlgType, isDataFamilyAppType, isPrimitiveType, isStrictType, isRuntimeRepTy, isRuntimeRepVar, isRuntimeRepKindedTy, dropRuntimeRepArgs, @@ -121,6 +128,7 @@ module Type ( -- ** Finding the kind of a type typeKind, isTypeLevPoly, resultIsLevPoly, + tcIsLiftedTypeKind, tcIsConstraintKind, tcReturnsConstraintKind, -- ** Common Kind liftedTypeKind, @@ -134,7 +142,7 @@ module Type ( noFreeVarsOfType, splitVisVarsOfType, splitVisVarsOfTypes, expandTypeSynonyms, - typeSize, + typeSize, occCheckExpand, -- * Well-scoped lists of variables dVarSetElemsWellScoped, toposortTyVars, tyCoVarsOfTypeWellScoped, @@ -161,14 +169,17 @@ module Type ( emptyTvSubstEnv, emptyTCvSubst, mkEmptyTCvSubst, mkTCvSubst, zipTvSubst, mkTvSubstPrs, + zipTCvSubst, notElemTCvSubst, getTvSubstEnv, setTvSubstEnv, zapTCvSubst, getTCvInScope, getTCvSubstRangeFVs, extendTCvInScope, extendTCvInScopeList, extendTCvInScopeSet, extendTCvSubst, extendCvSubst, - extendTvSubst, extendTvSubstBinder, + extendTvSubst, extendTvSubstBinderAndInScope, extendTvSubstList, extendTvSubstAndInScope, + extendTCvSubstList, extendTvSubstWithClone, + extendTCvSubstWithClone, isInScope, composeTCvSubstEnv, composeTCvSubst, zipTyEnv, zipCoEnv, isEmptyTCvSubst, unionTCvSubst, @@ -178,33 +189,37 @@ module Type ( substTyUnchecked, substTysUnchecked, substThetaUnchecked, substTyWithUnchecked, substCoUnchecked, substCoWithUnchecked, - substTyVarBndr, substTyVar, substTyVars, + substTyVarBndr, substTyVarBndrs, substTyVar, substTyVars, + substVarBndr, substVarBndrs, cloneTyVarBndr, cloneTyVarBndrs, lookupTyVar, -- * Pretty-printing pprType, pprParendType, pprPrecType, pprTypeApp, pprTyThingCategory, pprShortTyThing, - pprTvBndr, pprTvBndrs, pprForAll, pprUserForAll, + pprTCvBndr, pprTCvBndrs, pprForAll, pprUserForAll, pprSigmaType, ppSuggestExplicitKinds, pprTheta, pprThetaArrowTy, pprClassPred, pprKind, pprParendKind, pprSourceTyCon, - TyPrec(..), maybeParen, - pprTyVar, pprTyVars, pprPrefixApp, pprArrowChain, + PprPrec(..), topPrec, sigPrec, opPrec, funPrec, appPrec, maybeParen, + pprTyVar, pprTyVars, + pprWithTYPE, -- * Tidying type related things up for printing tidyType, tidyTypes, tidyOpenType, tidyOpenTypes, tidyOpenKind, - tidyTyCoVarBndr, tidyTyCoVarBndrs, tidyFreeTyCoVars, + tidyVarBndr, tidyVarBndrs, tidyFreeTyCoVars, tidyOpenTyCoVar, tidyOpenTyCoVars, - tidyTyVarOcc, + tidyTyCoVarOcc, tidyTopType, tidyKind, - tidyTyVarBinder, tidyTyVarBinders + tidyTyCoVarBinder, tidyTyCoVarBinders ) where #include "HsVersions.h" +import GhcPrelude + import BasicTypes -- We import the representation and primitive functions from TyCoRep. @@ -226,19 +241,23 @@ import {-# SOURCE #-} TysWiredIn ( listTyCon, typeNatKind , typeSymbolKind, liftedTypeKind ) import PrelNames import CoAxiom -import {-# SOURCE #-} Coercion +import {-# SOURCE #-} Coercion( mkNomReflCo, mkGReflCo, mkReflCo + , mkTyConAppCo, mkAppCo, mkCoVarCo, mkAxiomRuleCo + , mkForAllCo, mkFunCo, mkAxiomInstCo, mkUnivCo + , mkSymCo, mkTransCo, mkNthCo, mkLRCo, mkInstCo + , mkKindCo, mkSubCo, mkFunCo, mkAxiomInstCo + , decomposePiCos, coercionKind, coercionType + , isReflexiveCo, seqCo ) -- others import Util import Outputable import FastString import Pair +import DynFlags ( gopt_set, GeneralFlag(Opt_PrintExplicitRuntimeReps) ) import ListSetOps import Digraph import Unique ( nonDetCmpUnique ) -import SrcLoc ( SrcSpan ) -import OccName ( OccName ) -import Name ( mkInternalName ) import Maybes ( orElse ) import Data.Maybe ( isJust, mapMaybe ) @@ -298,7 +317,7 @@ import Control.Arrow ( first, second ) -- -- You don't normally have to worry about this, as the utility functions in -- this module will automatically convert a source into a representation type --- if they are spotted, to the best of it's abilities. If you don't want this +-- if they are spotted, to the best of its abilities. If you don't want this -- to happen, use the equivalent functions from the "TcType" module. {- @@ -321,33 +340,10 @@ See also Trac #11715, which tracks removing this inconsistency. -} -{-# INLINE coreView #-} -coreView :: Type -> Maybe Type --- ^ This function Strips off the /top layer only/ of a type synonym --- application (if any) its underlying representation type. --- Returns Nothing if there is nothing to look through. --- This function considers 'Constraint' to be a synonym of @TYPE LiftedRep@. --- --- By being non-recursive and inlined, this case analysis gets efficiently --- joined onto the case analysis that the caller is already doing -coreView (TyConApp tc tys) | Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys - = Just (mkAppTys (substTy (mkTvSubstPrs tenv) rhs) tys') - -- The free vars of 'rhs' should all be bound by 'tenv', so it's - -- ok to use 'substTy' here. - -- See also Note [The substitution invariant] in TyCoRep. - -- Its important to use mkAppTys, rather than (foldl AppTy), - -- because the function part might well return a - -- partially-applied type constructor; indeed, usually will! -coreView (TyConApp tc []) - | isStarKindSynonymTyCon tc - = Just liftedTypeKind - -coreView _ = Nothing - -- | Gives the typechecker view of a type. This unwraps synonyms but -- leaves 'Constraint' alone. c.f. coreView, which turns Constraint into -- TYPE LiftedRep. Returns Nothing if no unwrapping happens. --- See also Note [coreView vs tcView] in Type. +-- See also Note [coreView vs tcView] {-# INLINE tcView #-} tcView :: Type -> Maybe Type tcView (TyConApp tc tys) | Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys @@ -360,6 +356,28 @@ tcView (TyConApp tc tys) | Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys -- partially-applied type constructor; indeed, usually will! tcView _ = Nothing +{-# INLINE coreView #-} +coreView :: Type -> Maybe Type +-- ^ This function Strips off the /top layer only/ of a type synonym +-- application (if any) its underlying representation type. +-- Returns Nothing if there is nothing to look through. +-- This function considers 'Constraint' to be a synonym of @TYPE LiftedRep@. +-- +-- By being non-recursive and inlined, this case analysis gets efficiently +-- joined onto the case analysis that the caller is already doing +coreView ty@(TyConApp tc tys) + | Just (tenv, rhs, tys') <- expandSynTyCon_maybe tc tys + = Just (mkAppTys (substTy (mkTvSubstPrs tenv) rhs) tys') + -- This equation is exactly like tcView + + -- At the Core level, Constraint = Type + -- See Note [coreView vs tcView] + | isConstraintKindCon tc + = ASSERT2( null tys, ppr ty ) + Just liftedTypeKind + +coreView _ = Nothing + ----------------------------------------------- expandTypeSynonyms :: Type -> Type -- ^ Expand out all type synonyms. Actually, it'd suffice to expand out @@ -396,14 +414,19 @@ expandTypeSynonyms ty go subst (AppTy t1 t2) = mkAppTy (go subst t1) (go subst t2) go subst (FunTy arg res) = mkFunTy (go subst arg) (go subst res) - go subst (ForAllTy (TvBndr tv vis) t) - = let (subst', tv') = substTyVarBndrCallback go subst tv in - ForAllTy (TvBndr tv' vis) (go subst' t) + go subst (ForAllTy (Bndr tv vis) t) + = let (subst', tv') = substVarBndrUsing go subst tv in + ForAllTy (Bndr tv' vis) (go subst' t) go subst (CastTy ty co) = mkCastTy (go subst ty) (go_co subst co) go subst (CoercionTy co) = mkCoercionTy (go_co subst co) - go_co subst (Refl r ty) - = mkReflCo r (go subst ty) + go_mco _ MRefl = MRefl + go_mco subst (MCo co) = MCo (go_co subst co) + + go_co subst (Refl ty) + = mkNomReflCo (go subst ty) + go_co subst (GRefl r ty mco) + = mkGReflCo r (go subst ty) (go_mco subst mco) -- NB: coercions are always expanded upon creation go_co subst (TyConAppCo r tc args) = mkTyConAppCo r tc (map (go_co subst) args) @@ -424,31 +447,31 @@ expandTypeSynonyms ty = mkSymCo (go_co subst co) go_co subst (TransCo co1 co2) = mkTransCo (go_co subst co1) (go_co subst co2) - go_co subst (NthCo n co) - = mkNthCo n (go_co subst co) + go_co subst (NthCo r n co) + = mkNthCo r n (go_co subst co) go_co subst (LRCo lr co) = mkLRCo lr (go_co subst co) go_co subst (InstCo co arg) = mkInstCo (go_co subst co) (go_co subst arg) - go_co subst (CoherenceCo co1 co2) - = mkCoherenceCo (go_co subst co1) (go_co subst co2) go_co subst (KindCo co) = mkKindCo (go_co subst co) go_co subst (SubCo co) = mkSubCo (go_co subst co) - go_co subst (AxiomRuleCo ax cs) = AxiomRuleCo ax (map (go_co subst) cs) + go_co subst (AxiomRuleCo ax cs) + = AxiomRuleCo ax (map (go_co subst) cs) + go_co _ (HoleCo h) + = pprPanic "expandTypeSynonyms hit a hole" (ppr h) go_prov _ UnsafeCoerceProv = UnsafeCoerceProv go_prov subst (PhantomProv co) = PhantomProv (go_co subst co) go_prov subst (ProofIrrelProv co) = ProofIrrelProv (go_co subst co) go_prov _ p@(PluginProv _) = p - go_prov _ (HoleProv h) = pprPanic "expandTypeSynonyms hit a hole" (ppr h) -- the "False" and "const" are to accommodate the type of - -- substForAllCoBndrCallback, which is general enough to + -- substForAllCoBndrUsing, which is general enough to -- handle coercion optimization (which sometimes swaps the -- order of a coercion) - go_cobndr subst = substForAllCoBndrCallback False (go_co subst) subst + go_cobndr subst = substForAllCoBndrUsing False (go_co subst) subst {- ************************************************************************ @@ -463,11 +486,11 @@ on all variables and binding sites. Primarily used for zonking. Note [Efficiency for mapCoercion ForAllCo case] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As noted in Note [Forall coercions] in TyCoRep, a ForAllCo is a bit redundant. -It stores a TyVar and a Coercion, where the kind of the TyVar always matches +It stores a TyCoVar and a Coercion, where the kind of the TyCoVar always matches the left-hand kind of the coercion. This is convenient lots of the time, but not when mapping a function over a coercion. -The problem is that tcm_tybinder will affect the TyVar's kind and +The problem is that tcm_tybinder will affect the TyCoVar's kind and mapCoercion will affect the Coercion, and we hope that the results will be the same. Even if they are the same (which should generally happen with correct algorithms), then there is an efficiency issue. In particular, @@ -494,35 +517,42 @@ this one change made a 20% allocation difference in perf/compiler/T5030. data TyCoMapper env m = TyCoMapper { tcm_smart :: Bool -- ^ Should the new type be created with smart - -- constructors? + -- constructors? , tcm_tyvar :: env -> TyVar -> m Type , tcm_covar :: env -> CoVar -> m Coercion - , tcm_hole :: env -> CoercionHole -> Role - -> Type -> Type -> m Coercion - -- ^ What to do with coercion holes. See Note [Coercion holes] in - -- TyCoRep. + , tcm_hole :: env -> CoercionHole -> m Coercion + -- ^ What to do with coercion holes. + -- See Note [Coercion holes] in TyCoRep. - , tcm_tybinder :: env -> TyVar -> ArgFlag -> m (env, TyVar) + , tcm_tycobinder :: env -> TyCoVar -> ArgFlag -> m (env, TyCoVar) -- ^ The returned env is used in the extended scope + + , tcm_tycon :: TyCon -> m TyCon + -- ^ This is used only to turn 'TcTyCon's into 'TyCon's. + -- See Note [Type checking recursive type and class declarations] + -- in TcTyClsDecls } {-# INLINABLE mapType #-} -- See Note [Specialising mappers] mapType :: Monad m => TyCoMapper env m -> env -> Type -> m Type mapType mapper@(TyCoMapper { tcm_smart = smart, tcm_tyvar = tyvar - , tcm_tybinder = tybinder }) + , tcm_tycobinder = tycobinder, tcm_tycon = tycon }) env ty = go ty where go (TyVarTy tv) = tyvar env tv go (AppTy t1 t2) = mkappty <$> go t1 <*> go t2 - go t@(TyConApp _ []) = return t -- avoid allocation in this exceedingly - -- common case (mostly, for *) - go (TyConApp tc tys) = mktyconapp tc <$> mapM go tys + go t@(TyConApp tc []) | not (isTcTyCon tc) + = return t -- avoid allocation in this exceedingly + -- common case (mostly, for *) + go (TyConApp tc tys) + = do { tc' <- tycon tc + ; mktyconapp tc' <$> mapM go tys } go (FunTy arg res) = FunTy <$> go arg <*> go res - go (ForAllTy (TvBndr tv vis) inner) - = do { (env', tv') <- tybinder env tv vis + go (ForAllTy (Bndr tv vis) inner) + = do { (env', tv') <- tycobinder env tv vis ; inner' <- mapType mapper env' inner - ; return $ ForAllTy (TvBndr tv' vis) inner' } + ; return $ ForAllTy (Bndr tv' vis) inner' } go ty@(LitTy {}) = return ty go (CastTy ty co) = mkcastty <$> go ty <*> mapCoercion mapper env co go (CoercionTy co) = CoercionTy <$> mapCoercion mapper env co @@ -535,17 +565,23 @@ mapType mapper@(TyCoMapper { tcm_smart = smart, tcm_tyvar = tyvar mapCoercion :: Monad m => TyCoMapper env m -> env -> Coercion -> m Coercion mapCoercion mapper@(TyCoMapper { tcm_smart = smart, tcm_covar = covar - , tcm_hole = cohole, tcm_tybinder = tybinder }) + , tcm_hole = cohole, tcm_tycobinder = tycobinder + , tcm_tycon = tycon }) env co = go co where - go (Refl r ty) = Refl r <$> mapType mapper env ty + go_mco MRefl = return MRefl + go_mco (MCo co) = MCo <$> (go co) + + go (Refl ty) = Refl <$> mapType mapper env ty + go (GRefl r ty mco) = mkgreflco r <$> mapType mapper env ty <*> (go_mco mco) go (TyConAppCo r tc args) - = mktyconappco r tc <$> mapM go args + = do { tc' <- tycon tc + ; mktyconappco r tc' <$> mapM go args } go (AppCo c1 c2) = mkappco <$> go c1 <*> go c2 go (ForAllCo tv kind_co co) = do { kind_co' <- go kind_co - ; (env', tv') <- tybinder env tv Inferred + ; (env', tv') <- tycobinder env tv Inferred ; co' <- mapCoercion mapper env' co ; return $ mkforallco tv' kind_co' co' } -- See Note [Efficiency for mapCoercion ForAllCo case] @@ -553,18 +589,16 @@ mapCoercion mapper@(TyCoMapper { tcm_smart = smart, tcm_covar = covar go (CoVarCo cv) = covar env cv go (AxiomInstCo ax i args) = mkaxiominstco ax i <$> mapM go args - go (UnivCo (HoleProv hole) r t1 t2) - = cohole env hole r t1 t2 + go (HoleCo hole) = cohole env hole go (UnivCo p r t1 t2) = mkunivco <$> go_prov p <*> pure r <*> mapType mapper env t1 <*> mapType mapper env t2 go (SymCo co) = mksymco <$> go co go (TransCo c1 c2) = mktransco <$> go c1 <*> go c2 go (AxiomRuleCo r cos) = AxiomRuleCo r <$> mapM go cos - go (NthCo i co) = mknthco i <$> go co + go (NthCo r i co) = mknthco r i <$> go co go (LRCo lr co) = mklrco lr <$> go co go (InstCo co arg) = mkinstco <$> go co <*> go arg - go (CoherenceCo c1 c2) = mkcoherenceco <$> go c1 <*> go c2 go (KindCo co) = mkkindco <$> go co go (SubCo co) = mksubco <$> go co @@ -572,19 +606,18 @@ mapCoercion mapper@(TyCoMapper { tcm_smart = smart, tcm_covar = covar go_prov (PhantomProv co) = PhantomProv <$> go co go_prov (ProofIrrelProv co) = ProofIrrelProv <$> go co go_prov p@(PluginProv _) = return p - go_prov (HoleProv _) = panic "mapCoercion" ( mktyconappco, mkappco, mkaxiominstco, mkunivco - , mksymco, mktransco, mknthco, mklrco, mkinstco, mkcoherenceco - , mkkindco, mksubco, mkforallco) + , mksymco, mktransco, mknthco, mklrco, mkinstco + , mkkindco, mksubco, mkforallco, mkgreflco) | smart = ( mkTyConAppCo, mkAppCo, mkAxiomInstCo, mkUnivCo - , mkSymCo, mkTransCo, mkNthCo, mkLRCo, mkInstCo, mkCoherenceCo - , mkKindCo, mkSubCo, mkForAllCo ) + , mkSymCo, mkTransCo, mkNthCo, mkLRCo, mkInstCo + , mkKindCo, mkSubCo, mkForAllCo, mkGReflCo ) | otherwise = ( TyConAppCo, AppCo, AxiomInstCo, UnivCo - , SymCo, TransCo, NthCo, LRCo, InstCo, CoherenceCo - , KindCo, SubCo, ForAllCo ) + , SymCo, TransCo, NthCo, LRCo, InstCo + , KindCo, SubCo, ForAllCo, GRefl ) {- ************************************************************************ @@ -615,8 +648,8 @@ getTyVar_maybe ty | Just ty' <- coreView ty = getTyVar_maybe ty' | otherwise = repGetTyVar_maybe ty -- | If the type is a tyvar, possibly under a cast, returns it, along --- with the coercion. Thus, the co is :: kind tv ~R kind type -getCastedTyVar_maybe :: Type -> Maybe (TyVar, Coercion) +-- with the coercion. Thus, the co is :: kind tv ~N kind ty +getCastedTyVar_maybe :: Type -> Maybe (TyVar, CoercionN) getCastedTyVar_maybe ty | Just ty' <- coreView ty = getCastedTyVar_maybe ty' getCastedTyVar_maybe (CastTy (TyVarTy tv) co) = Just (tv, co) getCastedTyVar_maybe (TyVarTy tv) @@ -661,6 +694,11 @@ the type checker (e.g. when matching type-function equations). -- | Applies a type to another, as in e.g. @k a@ mkAppTy :: Type -> Type -> Type + -- See Note [Respecting definitional equality], invariant (EQ1). +mkAppTy (CastTy fun_ty co) arg_ty + | ([arg_co], res_co) <- decomposePiCos co (coercionKind co) [arg_ty] + = (fun_ty `mkAppTy` (arg_ty `mkCastTy` arg_co)) `mkCastTy` res_co + mkAppTy (TyConApp tc tys) ty2 = mkTyConApp tc (tys ++ [ty2]) mkAppTy ty1 ty2 = AppTy ty1 ty2 -- Note that the TyConApp could be an @@ -674,8 +712,17 @@ mkAppTy ty1 ty2 = AppTy ty1 ty2 mkAppTys :: Type -> [Type] -> Type mkAppTys ty1 [] = ty1 +mkAppTys (CastTy fun_ty co) arg_tys -- much more efficient then nested mkAppTy + -- Why do this? See (EQ1) of + -- Note [Respecting definitional equality] + -- in TyCoRep + = foldl' AppTy ((mkAppTys fun_ty casted_arg_tys) `mkCastTy` res_co) leftovers + where + (arg_cos, res_co) = decomposePiCos co (coercionKind co) arg_tys + (args_to_cast, leftovers) = splitAtList arg_cos arg_tys + casted_arg_tys = zipWith mkCastTy args_to_cast arg_cos mkAppTys (TyConApp tc tys1) tys2 = mkTyConApp tc (tys1 ++ tys2) -mkAppTys ty1 tys2 = foldl AppTy ty1 tys2 +mkAppTys ty1 tys2 = foldl' AppTy ty1 tys2 ------------- splitAppTy_maybe :: Type -> Maybe (Type, Type) @@ -687,40 +734,41 @@ splitAppTy_maybe ty | Just ty' <- coreView ty splitAppTy_maybe ty = repSplitAppTy_maybe ty ------------- -repSplitAppTy_maybe :: Type -> Maybe (Type,Type) +repSplitAppTy_maybe :: HasDebugCallStack => Type -> Maybe (Type,Type) -- ^ Does the AppTy split as in 'splitAppTy_maybe', but assumes that -- any Core view stuff is already done repSplitAppTy_maybe (FunTy ty1 ty2) - | Just rep1 <- getRuntimeRep_maybe ty1 - , Just rep2 <- getRuntimeRep_maybe ty2 = Just (TyConApp funTyCon [rep1, rep2, ty1], ty2) + where + rep1 = getRuntimeRep ty1 + rep2 = getRuntimeRep ty2 - | otherwise - = pprPanic "repSplitAppTy_maybe" (ppr ty1 $$ ppr ty2) repSplitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2) + repSplitAppTy_maybe (TyConApp tc tys) | mightBeUnsaturatedTyCon tc || tys `lengthExceeds` tyConArity tc , Just (tys', ty') <- snocView tys = Just (TyConApp tc tys', ty') -- Never create unsaturated type family apps! + repSplitAppTy_maybe _other = Nothing --- this one doesn't braek apart (c => t). +-- This one doesn't break apart (c => t). -- See Note [Decomposing fat arrow c=>t] -- Defined here to avoid module loops between Unify and TcType. tcRepSplitAppTy_maybe :: Type -> Maybe (Type,Type) -- ^ Does the AppTy split as in 'tcSplitAppTy_maybe', but assumes that -- any coreView stuff is already done. Refuses to look through (c => t) tcRepSplitAppTy_maybe (FunTy ty1 ty2) - | isConstraintKind (typeKind ty1) + | isPredTy ty1 = Nothing -- See Note [Decomposing fat arrow c=>t] - | Just rep1 <- getRuntimeRep_maybe ty1 - , Just rep2 <- getRuntimeRep_maybe ty2 + | otherwise = Just (TyConApp funTyCon [rep1, rep2, ty1], ty2) + where + rep1 = getRuntimeRep ty1 + rep2 = getRuntimeRep ty2 - | otherwise - = pprPanic "repSplitAppTy_maybe" (ppr ty1 $$ ppr ty2) tcRepSplitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2) tcRepSplitAppTy_maybe (TyConApp tc tys) | mightBeUnsaturatedTyCon tc || tys `lengthExceeds` tyConArity tc @@ -728,31 +776,20 @@ tcRepSplitAppTy_maybe (TyConApp tc tys) = Just (TyConApp tc tys', ty') -- Never create unsaturated type family apps! tcRepSplitAppTy_maybe _other = Nothing --- | Split a type constructor application into its type constructor and --- applied types. Note that this may fail in the case of a 'FunTy' with an --- argument of unknown kind 'FunTy' (e.g. @FunTy (a :: k) Int@. since the kind --- of @a@ isn't of the form @TYPE rep@). Consequently, you may need to zonk your --- type before using this function. --- --- If you only need the 'TyCon', consider using 'tcTyConAppTyCon_maybe'. -tcSplitTyConApp_maybe :: HasCallStack => Type -> Maybe (TyCon, [Type]) --- Defined here to avoid module loops between Unify and TcType. -tcSplitTyConApp_maybe ty | Just ty' <- tcView ty = tcSplitTyConApp_maybe ty' -tcSplitTyConApp_maybe ty = tcRepSplitTyConApp_maybe ty - -- | Like 'tcSplitTyConApp_maybe' but doesn't look through type synonyms. tcRepSplitTyConApp_maybe :: HasCallStack => Type -> Maybe (TyCon, [Type]) -- Defined here to avoid module loops between Unify and TcType. -tcRepSplitTyConApp_maybe (TyConApp tc tys) = Just (tc, tys) +tcRepSplitTyConApp_maybe (TyConApp tc tys) + = Just (tc, tys) + tcRepSplitTyConApp_maybe (FunTy arg res) - | Just arg_rep <- getRuntimeRep_maybe arg - , Just res_rep <- getRuntimeRep_maybe res = Just (funTyCon, [arg_rep, res_rep, arg, res]) + where + arg_rep = getRuntimeRep arg + res_rep = getRuntimeRep res - | otherwise - = pprPanic "tcRepSplitTyConApp_maybe" (ppr arg $$ ppr res) -tcRepSplitTyConApp_maybe _ = Nothing - +tcRepSplitTyConApp_maybe _ + = Nothing ------------- splitAppTy :: Type -> (Type, Type) @@ -779,17 +816,16 @@ splitAppTys ty = split ty ty [] in (TyConApp tc tc_args1, tc_args2 ++ args) split _ (FunTy ty1 ty2) args - | Just rep1 <- getRuntimeRep_maybe ty1 - , Just rep2 <- getRuntimeRep_maybe ty2 = ASSERT( null args ) (TyConApp funTyCon [], [rep1, rep2, ty1, ty2]) + where + rep1 = getRuntimeRep ty1 + rep2 = getRuntimeRep ty2 - | otherwise - = pprPanic "splitAppTys" (ppr ty1 $$ ppr ty2 $$ ppr args) split orig_ty _ args = (orig_ty, args) -- | Like 'splitAppTys', but doesn't look through type synonyms -repSplitAppTys :: Type -> (Type, [Type]) +repSplitAppTys :: HasDebugCallStack => Type -> (Type, [Type]) repSplitAppTys ty = split ty [] where split (AppTy ty arg) args = split ty (arg:args) @@ -800,13 +836,12 @@ repSplitAppTys ty = split ty [] in (TyConApp tc tc_args1, tc_args2 ++ args) split (FunTy ty1 ty2) args - | Just rep1 <- getRuntimeRep_maybe ty1 - , Just rep2 <- getRuntimeRep_maybe ty2 = ASSERT( null args ) (TyConApp funTyCon [], [rep1, rep2, ty1, ty2]) + where + rep1 = getRuntimeRep ty1 + rep2 = getRuntimeRep ty2 - | otherwise - = pprPanic "repSplitAppTys" (ppr ty1 $$ ppr ty2 $$ ppr args) split ty args = (ty, args) {- @@ -832,6 +867,11 @@ isStrLitTy ty | Just ty1 <- coreView ty = isStrLitTy ty1 isStrLitTy (LitTy (StrTyLit s)) = Just s isStrLitTy _ = Nothing +-- | Is this a type literal (symbol or numeric). +isLitTy :: Type -> Maybe TyLit +isLitTy ty | Just ty1 <- coreView ty = isLitTy ty1 +isLitTy (LitTy l) = Just l +isLitTy _ = Nothing -- | Is this type a custom user error? -- If so, give us the kind and the error message. @@ -868,7 +908,7 @@ pprUserTypeErrorTy ty = | tyConName tc == typeErrorVAppendDataConName -> pprUserTypeErrorTy t1 $$ pprUserTypeErrorTy t2 - -- An uneavaluated type function + -- An unevaluated type function _ -> ppr ty @@ -882,7 +922,7 @@ pprUserTypeErrorTy ty = Note [Representation of function types] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Functions (e.g. Int -> Char) are can be thought of as being applications +Functions (e.g. Int -> Char) can be thought of as being applications of funTyCon (known in Haskell surface syntax as (->)), (->) :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) @@ -943,26 +983,25 @@ funArgTy ty | Just ty' <- coreView ty = funArgTy ty' funArgTy (FunTy arg _res) = arg funArgTy ty = pprPanic "funArgTy" (ppr ty) -piResultTy :: Type -> Type -> Type +-- ^ Just like 'piResultTys' but for a single argument +-- Try not to iterate 'piResultTy', because it's inefficient to substitute +-- one variable at a time; instead use 'piResultTys" +piResultTy :: HasDebugCallStack => Type -> Type -> Type piResultTy ty arg = case piResultTy_maybe ty arg of Just res -> res Nothing -> pprPanic "piResultTy" (ppr ty $$ ppr arg) piResultTy_maybe :: Type -> Type -> Maybe Type - --- ^ Just like 'piResultTys' but for a single argument --- Try not to iterate 'piResultTy', because it's inefficient to substitute --- one variable at a time; instead use 'piResultTys" piResultTy_maybe ty arg | Just ty' <- coreView ty = piResultTy_maybe ty' arg | FunTy _ res <- ty = Just res - | ForAllTy (TvBndr tv _) res <- ty + | ForAllTy (Bndr tv _) res <- ty = let empty_subst = mkEmptyTCvSubst $ mkInScopeSet $ tyCoVarsOfTypes [arg,res] - in Just (substTy (extendTvSubst empty_subst tv arg) res) + in Just (substTy (extendTCvSubst empty_subst tv arg) res) | otherwise = Nothing @@ -988,7 +1027,7 @@ piResultTy_maybe ty arg -- so we pay attention to efficiency, especially in the special case -- where there are no for-alls so we are just dropping arrows from -- a function type/kind. -piResultTys :: Type -> [Type] -> Type +piResultTys :: HasDebugCallStack => Type -> [Type] -> Type piResultTys ty [] = ty piResultTys ty orig_args@(arg:args) | Just ty' <- coreView ty @@ -997,34 +1036,39 @@ piResultTys ty orig_args@(arg:args) | FunTy _ res <- ty = piResultTys res args - | ForAllTy (TvBndr tv _) res <- ty - = go (extendVarEnv emptyTvSubstEnv tv arg) res args + | ForAllTy (Bndr tv _) res <- ty + = go (extendTCvSubst init_subst tv arg) res args | otherwise = pprPanic "piResultTys1" (ppr ty $$ ppr orig_args) where - in_scope = mkInScopeSet (tyCoVarsOfTypes (ty:orig_args)) + init_subst = mkEmptyTCvSubst $ mkInScopeSet (tyCoVarsOfTypes (ty:orig_args)) - go :: TvSubstEnv -> Type -> [Type] -> Type - go tv_env ty [] = substTy (mkTvSubst in_scope tv_env) ty + go :: TCvSubst -> Type -> [Type] -> Type + go subst ty [] = substTy subst ty - go tv_env ty all_args@(arg:args) + go subst ty all_args@(arg:args) | Just ty' <- coreView ty - = go tv_env ty' all_args + = go subst ty' all_args | FunTy _ res <- ty - = go tv_env res args + = go subst res args - | ForAllTy (TvBndr tv _) res <- ty - = go (extendVarEnv tv_env tv arg) res args + | ForAllTy (Bndr tv _) res <- ty + = go (extendTCvSubst subst tv arg) res args - | TyVarTy tv <- ty - , Just ty' <- lookupVarEnv tv_env tv - -- Deals with piResultTys (forall a. a) [forall b.b, Int] - = piResultTys ty' all_args + | not (isEmptyTCvSubst subst) -- See Note [Care with kind instantiation] + = go init_subst + (substTy subst ty) + all_args | otherwise - = pprPanic "piResultTys2" (ppr ty $$ ppr orig_args $$ ppr all_args) + = -- We have not run out of arguments, but the function doesn't + -- have the right kind to apply to them; so panic. + -- Without the explicit isEmptyVarEnv test, an ill-kinded type + -- would give an infniite loop, which is very unhelpful + -- c.f. Trac #15473 + pprPanic "piResultTys2" (ppr ty $$ ppr orig_args $$ ppr all_args) applyTysX :: [TyVar] -> Type -> [Type] -> Type -- applyTyxX beta-reduces (/\tvs. body_ty) arg_tys @@ -1038,7 +1082,35 @@ applyTysX tvs body_ty arg_tys pp_stuff = vcat [ppr tvs, ppr body_ty, ppr arg_tys] n_tvs = length tvs -{- + + +{- Note [Care with kind instantiation] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Suppose we have + T :: forall k. k +and we are finding the kind of + T (forall b. b -> b) * Int +Then + T (forall b. b->b) :: k[ k :-> forall b. b->b] + :: forall b. b -> b +So + T (forall b. b->b) * :: (b -> b)[ b :-> *] + :: * -> * + +In other words we must intantiate the forall! + +Similarly (Trac #15428) + S :: forall k f. k -> f k +and we are finding the kind of + S * (* ->) Int Bool +We have + S * (* ->) :: (k -> f k)[ k :-> *, f :-> (* ->)] + :: * -> * -> * +So again we must instantiate. + +The same thing happens in ToIface.toIfaceAppArgsX. + + --------------------------------------------------------------------- TyConApp ~~~~~~~~ @@ -1085,7 +1157,7 @@ tyConAppArgs_maybe (FunTy arg res) | Just rep1 <- getRuntimeRep_maybe arg , Just rep2 <- getRuntimeRep_maybe res = Just [rep1, rep2, arg, res] -tyConAppArgs_maybe _ = Nothing +tyConAppArgs_maybe _ = Nothing tyConAppArgs :: Type -> [Type] tyConAppArgs ty = tyConAppArgs_maybe ty `orElse` pprPanic "tyConAppArgs" (ppr ty) @@ -1116,12 +1188,9 @@ splitTyConApp_maybe ty = repSplitTyConApp_maybe ty repSplitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type]) repSplitTyConApp_maybe (TyConApp tc tys) = Just (tc, tys) repSplitTyConApp_maybe (FunTy arg res) - | Just rep1 <- getRuntimeRep_maybe arg - , Just rep2 <- getRuntimeRep_maybe res - = Just (funTyCon, [rep1, rep2, arg, res]) - | otherwise - = pprPanic "repSplitTyConApp_maybe" - (ppr arg $$ ppr res $$ ppr (typeKind res)) + | Just arg_rep <- getRuntimeRep_maybe arg + , Just res_rep <- getRuntimeRep_maybe res + = Just (funTyCon, [arg_rep, res_rep, arg, res]) repSplitTyConApp_maybe _ = Nothing -- | Attempts to tease a list type apart and gives the type of the elements if @@ -1131,10 +1200,6 @@ splitListTyConApp_maybe ty = case splitTyConApp_maybe ty of Just (tc,[e]) | tc == listTyCon -> Just e _other -> Nothing --- | What is the role assigned to the next parameter of this type? Usually, --- this will be 'Nominal', but if the type is a 'TyConApp', we may be able to --- do better. The type does *not* have to be well-kinded when applied for this --- to work! nextRole :: Type -> Role nextRole ty | Just (tc, tys) <- splitTyConApp_maybe ty @@ -1161,47 +1226,21 @@ newTyConInstRhs tycon tys ~~~~~~ A casted type has its *kind* casted into something new. -Note [No reflexive casts in types] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -As far as possible, we would like to maintain the following property: - - (*) If (t1 `eqType` t2), then t1 and t2 are treated identically within GHC. - -The (*) property is very useful, because we have a tendency to compare two -types to see if they're equal, and then arbitrarily choose one. We don't -want this arbitrary choice to then matter later on. Maintaining (*) means -that every function that looks at a structure of a type must think about -casts. In places where we directly pattern-match, this consideration is -forced by consideration of the CastTy constructor. - -But, when we call a splitXXX function, it's easy to ignore the possibility -of casts. In particular, splitTyConApp is used extensively, and we don't -want it to fail on (T a b c |> co). Happily, if we have - (T a b c |> co) `eqType` (T d e f) -then co must be reflexive. Why? eqType checks that the kinds are equal, as -well as checking that (a `eqType` d), (b `eqType` e), and (c `eqType` f). -By the kind check, we know that (T a b c |> co) and (T d e f) have the same -kind. So the only way that co could be non-reflexive is for (T a b c) to have -a different kind than (T d e f). But because T's kind is closed (all tycon kinds -are closed), the only way for this to happen is that one of the arguments has -to differ, leading to a contradiction. Thus, co is reflexive. - -Accordingly, by eliminating reflexive casts, splitTyConApp need not worry -about outermost casts to uphold (*). - -Unforunately, that's not the end of the story. Consider comparing - (T a b c) =? (T a b |> (co -> <Type>)) (c |> sym co) -These two types have the same kind (Type), but the left type is a TyConApp -while the right type is not. To handle this case, we will have to implement -some variant of the dreaded KPush algorithm (c.f. CoreOpt.pushCoDataCon). -This stone is left unturned for now, meaning that we don't yet uphold (*). - -The other place where (*) will be hard to guarantee is in splitAppTy, because -I (Richard E) can't think of a way to push coercions into AppTys. The good -news here is that splitAppTy is not used all that much, and so all clients of -that function can simply be told to use splitCastTy as well, in order to -uphold (*). This, too, is left undone, for now. +Note [Weird typing rule for ForAllTy] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Here is the (truncated) typing rule for the dependent ForAllTy: +inner : kind +------------------------------------ +ForAllTy (Bndr tyvar vis) inner : kind + +inner : TYPE r +------------------------------------ +ForAllTy (Bndr covar vis) inner : TYPE + +Note that when inside the binder is a tyvar, neither the inner type nor for +ForAllTy itself have to have kind *! But, it means that we should push any kind +casts through the ForAllTy. The only trouble is avoiding capture. -} splitCastTy_maybe :: Type -> Maybe (Type, Coercion) @@ -1211,24 +1250,39 @@ splitCastTy_maybe _ = Nothing -- | Make a 'CastTy'. The Coercion must be nominal. Checks the -- Coercion for reflexivity, dropping it if it's reflexive. --- See Note [No reflexive casts in types] +-- See Note [Respecting definitional equality] in TyCoRep mkCastTy :: Type -> Coercion -> Type -mkCastTy ty co | isReflexiveCo co = ty +mkCastTy ty co | isReflexiveCo co = ty -- (EQ2) from the Note -- NB: Do the slow check here. This is important to keep the splitXXX -- functions working properly. Otherwise, we may end up with something -- like (((->) |> something_reflexive_but_not_obviously_so) biz baz) -- fails under splitFunTy_maybe. This happened with the cheaper check -- in test dependent/should_compile/dynamic-paper. -mkCastTy (CastTy ty co1) co2 = mkCastTy ty (co1 `mkTransCo` co2) +mkCastTy (CastTy ty co1) co2 + -- (EQ3) from the Note + = mkCastTy ty (co1 `mkTransCo` co2) + -- call mkCastTy again for the reflexivity check + +mkCastTy (ForAllTy (Bndr tv vis) inner_ty) co + -- (EQ4) from the Note + | isTyVar tv + , let fvs = tyCoVarsOfCo co + = -- have to make sure that pushing the co in doesn't capture the bound var! + if tv `elemVarSet` fvs + then let empty_subst = mkEmptyTCvSubst (mkInScopeSet fvs) + (subst, tv') = substVarBndr empty_subst tv + in ForAllTy (Bndr tv' vis) (substTy subst inner_ty `mkCastTy` co) + else ForAllTy (Bndr tv vis) (inner_ty `mkCastTy` co) + mkCastTy ty co = CastTy ty co -tyConBindersTyBinders :: [TyConBinder] -> [TyBinder] --- Return the tyConBinders in TyBinder form -tyConBindersTyBinders = map to_tyb +tyConBindersTyCoBinders :: [TyConBinder] -> [TyCoBinder] +-- Return the tyConBinders in TyCoBinder form +tyConBindersTyCoBinders = map to_tyb where - to_tyb (TvBndr tv (NamedTCB vis)) = Named (TvBndr tv vis) - to_tyb (TvBndr tv AnonTCB) = Anon (tyVarKind tv) + to_tyb (Bndr tv (NamedTCB vis)) = Named (Bndr tv vis) + to_tyb (Bndr tv AnonTCB) = Anon (varType tv) {- -------------------------------------------------------------------- @@ -1280,26 +1334,40 @@ interfaces. Notably this plays a role in tcTySigs in TcBinds.hs. -- | Make a dependent forall over an Inferred (as opposed to Specified) -- variable +mkTyCoInvForAllTy :: TyCoVar -> Type -> Type +mkTyCoInvForAllTy tv ty + | isCoVar tv + , not (tv `elemVarSet` tyCoVarsOfType ty) + = mkFunTy (varType tv) ty + | otherwise + = ForAllTy (Bndr tv Inferred) ty + +-- | Like mkTyCoInvForAllTy, but tv should be a tyvar mkInvForAllTy :: TyVar -> Type -> Type mkInvForAllTy tv ty = ASSERT( isTyVar tv ) - ForAllTy (TvBndr tv Inferred) ty + ForAllTy (Bndr tv Inferred) ty -- | Like mkForAllTys, but assumes all variables are dependent and Inferred, -- a common case +mkTyCoInvForAllTys :: [TyCoVar] -> Type -> Type +mkTyCoInvForAllTys tvs ty = foldr mkTyCoInvForAllTy ty tvs + +-- | Like 'mkTyCoInvForAllTys', but tvs should be a list of tyvar mkInvForAllTys :: [TyVar] -> Type -> Type -mkInvForAllTys tvs ty = ASSERT( all isTyVar tvs ) - foldr mkInvForAllTy ty tvs +mkInvForAllTys tvs ty = foldr mkInvForAllTy ty tvs -- | Like mkForAllTys, but assumes all variables are dependent and specified, -- a common case mkSpecForAllTys :: [TyVar] -> Type -> Type mkSpecForAllTys tvs = ASSERT( all isTyVar tvs ) - mkForAllTys [ TvBndr tv Specified | tv <- tvs ] + -- covar is always Inferred, so all inputs should be tyvar + mkForAllTys [ Bndr tv Specified | tv <- tvs ] -- | Like mkForAllTys, but assumes all variables are dependent and visible mkVisForAllTys :: [TyVar] -> Type -> Type mkVisForAllTys tvs = ASSERT( all isTyVar tvs ) - mkForAllTys [ TvBndr tv Required | tv <- tvs ] + -- covar is always Inferred, so all inputs should be tyvar + mkForAllTys [ Bndr tv Required | tv <- tvs ] mkLamType :: Var -> Type -> Type -- ^ Makes a @(->)@ type or an implicit forall type, depending @@ -1310,46 +1378,67 @@ mkLamTypes :: [Var] -> Type -> Type -- ^ 'mkLamType' for multiple type or value arguments mkLamType v ty - | isTyVar v = ForAllTy (TvBndr v Inferred) ty - | otherwise = FunTy (varType v) ty + | isCoVar v + , v `elemVarSet` tyCoVarsOfType ty + = ForAllTy (Bndr v Inferred) ty + | isTyVar v + = ForAllTy (Bndr v Inferred) ty + | otherwise + = FunTy (varType v) ty mkLamTypes vs ty = foldr mkLamType ty vs --- | Given a list of type-level vars and a result type, makes TyBinders, preferring --- anonymous binders if the variable is, in fact, not dependent. --- All binders are /visible/. +-- | Given a list of type-level vars and a result kind, +-- makes TyCoBinders, preferring anonymous binders +-- if the variable is, in fact, not dependent. +-- e.g. mkTyConBindersPreferAnon [(k:*),(b:k),(c:k)] (k->k) +-- We want (k:*) Named, (b:k) Anon, (c:k) Anon +-- +-- All non-coercion binders are /visible/. mkTyConBindersPreferAnon :: [TyVar] -> Type -> [TyConBinder] -mkTyConBindersPreferAnon vars inner_ty = fst (go vars) +mkTyConBindersPreferAnon vars inner_ty = ASSERT( all isTyVar vars) + fst (go vars) where go :: [TyVar] -> ([TyConBinder], VarSet) -- also returns the free vars go [] = ([], tyCoVarsOfType inner_ty) - go (v:vs) | v `elemVarSet` fvs - = ( TvBndr v (NamedTCB Required) : binders + go (v:vs) | v `elemVarSet` fvs + = ( Bndr v (NamedTCB Required) : binders , fvs `delVarSet` v `unionVarSet` kind_vars ) | otherwise - = ( TvBndr v AnonTCB : binders + = ( Bndr v AnonTCB : binders , fvs `unionVarSet` kind_vars ) where (binders, fvs) = go vs kind_vars = tyCoVarsOfType $ tyVarKind v --- | Take a ForAllTy apart, returning the list of tyvars and the result type. +-- | Take a ForAllTy apart, returning the list of tycovars and the result type. -- This always succeeds, even if it returns only an empty list. Note that the -- result type returned may have free variables that were bound by a forall. -splitForAllTys :: Type -> ([TyVar], Type) +splitForAllTys :: Type -> ([TyCoVar], Type) splitForAllTys ty = split ty ty [] where split orig_ty ty tvs | Just ty' <- coreView ty = split orig_ty ty' tvs - split _ (ForAllTy (TvBndr tv _) ty) tvs = split ty ty (tv:tvs) - split orig_ty _ tvs = (reverse tvs, orig_ty) + split _ (ForAllTy (Bndr tv _) ty) tvs = split ty ty (tv:tvs) + split orig_ty _ tvs = (reverse tvs, orig_ty) + +-- | Like splitForAllTys, but split only for tyvars. +-- This always succeeds, even if it returns only an empty list. Note that the +-- result type returned may have free variables that were bound by a forall. +splitTyVarForAllTys :: Type -> ([TyVar], Type) +splitTyVarForAllTys ty = split ty ty [] + where + split orig_ty ty tvs | Just ty' <- coreView ty = split orig_ty ty' tvs + split _ (ForAllTy (Bndr tv _) ty) tvs | isTyVar tv = split ty ty (tv:tvs) + split orig_ty _ tvs = (reverse tvs, orig_ty) -- | Like 'splitPiTys' but split off only /named/ binders. -splitForAllTyVarBndrs :: Type -> ([TyVarBinder], Type) -splitForAllTyVarBndrs ty = split ty ty [] +splitForAllVarBndrs :: Type -> ([TyCoVarBinder], Type) +splitForAllVarBndrs ty = split ty ty [] where split orig_ty ty bs | Just ty' <- coreView ty = split orig_ty ty' bs - split _ (ForAllTy b res) bs = split res res (b:bs) - split orig_ty _ bs = (reverse bs, orig_ty) + split _ (ForAllTy b res) bs = split res res (b:bs) + split orig_ty _ bs = (reverse bs, orig_ty) +{-# INLINE splitForAllVarBndrs #-} -- | Checks whether this is a proper forall (with a named binder) isForAllTy :: Type -> Bool @@ -1357,6 +1446,18 @@ isForAllTy ty | Just ty' <- coreView ty = isForAllTy ty' isForAllTy (ForAllTy {}) = True isForAllTy _ = False +-- | Like `isForAllTy`, but returns True only if it is a tyvar binder +isForAllTy_ty :: Type -> Bool +isForAllTy_ty ty | Just ty' <- coreView ty = isForAllTy_ty ty' +isForAllTy_ty (ForAllTy (Bndr tv _) _) | isTyVar tv = True +isForAllTy_ty _ = False + +-- | Like `isForAllTy`, but returns True only if it is a covar binder +isForAllTy_co :: Type -> Bool +isForAllTy_co ty | Just ty' <- coreView ty = isForAllTy_co ty' +isForAllTy_co (ForAllTy (Bndr tv _) _) | isCoVar tv = True +isForAllTy_co _ = False + -- | Is this a function or forall? isPiTy :: Type -> Bool isPiTy ty | Just ty' <- coreView ty = isForAllTy ty' @@ -1365,7 +1466,7 @@ isPiTy (FunTy {}) = True isPiTy _ = False -- | Take a forall type apart, or panics if that is not possible. -splitForAllTy :: Type -> (TyVar, Type) +splitForAllTy :: Type -> (TyCoVar, Type) splitForAllTy ty | Just answer <- splitForAllTy_maybe ty = answer | otherwise = pprPanic "splitForAllTy" (ppr ty) @@ -1380,16 +1481,32 @@ dropForAlls ty = go ty -- | Attempts to take a forall type apart, but only if it's a proper forall, -- with a named binder -splitForAllTy_maybe :: Type -> Maybe (TyVar, Type) +splitForAllTy_maybe :: Type -> Maybe (TyCoVar, Type) splitForAllTy_maybe ty = go ty where go ty | Just ty' <- coreView ty = go ty' - go (ForAllTy (TvBndr tv _) ty) = Just (tv, ty) - go _ = Nothing + go (ForAllTy (Bndr tv _) ty) = Just (tv, ty) + go _ = Nothing + +-- | Like splitForAllTy_maybe, but only returns Just if it is a tyvar binder. +splitForAllTy_ty_maybe :: Type -> Maybe (TyCoVar, Type) +splitForAllTy_ty_maybe ty = go ty + where + go ty | Just ty' <- coreView ty = go ty' + go (ForAllTy (Bndr tv _) ty) | isTyVar tv = Just (tv, ty) + go _ = Nothing + +-- | Like splitForAllTy_maybe, but only returns Just if it is a covar binder. +splitForAllTy_co_maybe :: Type -> Maybe (TyCoVar, Type) +splitForAllTy_co_maybe ty = go ty + where + go ty | Just ty' <- coreView ty = go ty' + go (ForAllTy (Bndr tv _) ty) | isCoVar tv = Just (tv, ty) + go _ = Nothing -- | Attempts to take a forall type apart; works with proper foralls and -- functions -splitPiTy_maybe :: Type -> Maybe (TyBinder, Type) +splitPiTy_maybe :: Type -> Maybe (TyCoBinder, Type) splitPiTy_maybe ty = go ty where go ty | Just ty' <- coreView ty = go ty' @@ -1398,28 +1515,30 @@ splitPiTy_maybe ty = go ty go _ = Nothing -- | Takes a forall type apart, or panics -splitPiTy :: Type -> (TyBinder, Type) +splitPiTy :: Type -> (TyCoBinder, Type) splitPiTy ty | Just answer <- splitPiTy_maybe ty = answer | otherwise = pprPanic "splitPiTy" (ppr ty) --- | Split off all TyBinders to a type, splitting both proper foralls +-- | Split off all TyCoBinders to a type, splitting both proper foralls -- and functions -splitPiTys :: Type -> ([TyBinder], Type) -splitPiTys ty = split ty ty [] +splitPiTys :: Type -> ([TyCoBinder], Type) +splitPiTys ty = split ty ty where - split orig_ty ty bs | Just ty' <- coreView ty = split orig_ty ty' bs - split _ (ForAllTy b res) bs = split res res (Named b : bs) - split _ (FunTy arg res) bs = split res res (Anon arg : bs) - split orig_ty _ bs = (reverse bs, orig_ty) + split orig_ty ty | Just ty' <- coreView ty = split orig_ty ty' + split _ (ForAllTy b res) = let (bs, ty) = split res res + in (Named b : bs, ty) + split _ (FunTy arg res) = let (bs, ty) = split res res + in (Anon arg : bs, ty) + split orig_ty _ = ([], orig_ty) -- Like splitPiTys, but returns only *invisible* binders, including constraints -- Stops at the first visible binder -splitPiTysInvisible :: Type -> ([TyBinder], Type) +splitPiTysInvisible :: Type -> ([TyCoBinder], Type) splitPiTysInvisible ty = split ty ty [] where split orig_ty ty bs | Just ty' <- coreView ty = split orig_ty ty' bs - split _ (ForAllTy b@(TvBndr _ vis) res) bs + split _ (ForAllTy b@(Bndr _ vis) res) bs | isInvisibleArgFlag vis = split res res (Named b : bs) split _ (FunTy arg res) bs | isPredTy arg = split res res (Anon arg : bs) @@ -1427,11 +1546,12 @@ splitPiTysInvisible ty = split ty ty [] -- | Given a tycon and its arguments, filters out any invisible arguments filterOutInvisibleTypes :: TyCon -> [Type] -> [Type] -filterOutInvisibleTypes tc tys = snd $ partitionInvisibles tc id tys +filterOutInvisibleTypes tc tys = snd $ partitionInvisibleTypes tc tys --- | Like 'filterOutInvisibles', but works on 'TyVar's -filterOutInvisibleTyVars :: TyCon -> [TyVar] -> [TyVar] -filterOutInvisibleTyVars tc tvs = snd $ partitionInvisibles tc mkTyVarTy tvs +-- | Given a 'TyCon' and its arguments, partition the arguments into +-- (invisible arguments, visible arguments). +partitionInvisibleTypes :: TyCon -> [Type] -> ([Type], [Type]) +partitionInvisibleTypes tc tys = partitionInvisibles tc id tys -- | Given a tycon and a list of things (which correspond to arguments), -- partitions the things into @@ -1456,11 +1576,11 @@ partitionInvisibles :: TyCon -> (a -> Type) -> [a] -> ([a], [a]) partitionInvisibles tc get_ty = go emptyTCvSubst (tyConKind tc) where go _ _ [] = ([], []) - go subst (ForAllTy (TvBndr tv vis) res_ki) (x:xs) + go subst (ForAllTy (Bndr tv vis) res_ki) (x:xs) | isVisibleArgFlag vis = second (x :) (go subst' res_ki xs) | otherwise = first (x :) (go subst' res_ki xs) where - subst' = extendTvSubst subst tv (get_ty x) + subst' = extendTCvSubst subst tv (get_ty x) go subst (TyVarTy tv) xs | Just ki <- lookupTyVar subst tv = go subst ki xs go _ _ xs = ([], xs) -- something is ill-kinded. But this can happen @@ -1481,60 +1601,53 @@ isTauTy (CoercionTy _) = False -- Not sure about this {- %************************************************************************ %* * - TyBinders + TyCoBinders %* * %************************************************************************ -} --- | Make a named binder -mkTyVarBinder :: ArgFlag -> Var -> TyVarBinder -mkTyVarBinder vis var = TvBndr var vis - --- | Make many named binders -mkTyVarBinders :: ArgFlag -> [TyVar] -> [TyVarBinder] -mkTyVarBinders vis = map (mkTyVarBinder vis) - -- | Make an anonymous binder -mkAnonBinder :: Type -> TyBinder +mkAnonBinder :: Type -> TyCoBinder mkAnonBinder = Anon -- | Does this binder bind a variable that is /not/ erased? Returns -- 'True' for anonymous binders. -isAnonTyBinder :: TyBinder -> Bool -isAnonTyBinder (Named {}) = False -isAnonTyBinder (Anon {}) = True +isAnonTyCoBinder :: TyCoBinder -> Bool +isAnonTyCoBinder (Named {}) = False +isAnonTyCoBinder (Anon {}) = True -isNamedTyBinder :: TyBinder -> Bool -isNamedTyBinder (Named {}) = True -isNamedTyBinder (Anon {}) = False +isNamedTyCoBinder :: TyCoBinder -> Bool +isNamedTyCoBinder (Named {}) = True +isNamedTyCoBinder (Anon {}) = False -tyBinderType :: TyBinder -> Type +tyCoBinderVar_maybe :: TyCoBinder -> Maybe TyCoVar +tyCoBinderVar_maybe (Named tv) = Just $ binderVar tv +tyCoBinderVar_maybe _ = Nothing + +tyCoBinderType :: TyCoBinder -> Type -- Barely used -tyBinderType (Named tvb) = binderKind tvb +tyCoBinderType (Named tvb) = binderType tvb +tyCoBinderType (Anon ty) = ty + +tyBinderType :: TyBinder -> Type +tyBinderType (Named (Bndr tv _)) + = ASSERT( isTyVar tv ) + tyVarKind tv tyBinderType (Anon ty) = ty -- | Extract a relevant type, if there is one. -binderRelevantType_maybe :: TyBinder -> Maybe Type +binderRelevantType_maybe :: TyCoBinder -> Maybe Type binderRelevantType_maybe (Named {}) = Nothing binderRelevantType_maybe (Anon ty) = Just ty -- | Like 'maybe', but for binders. -caseBinder :: TyBinder -- ^ binder to scrutinize - -> (TyVarBinder -> a) -- ^ named case - -> (Type -> a) -- ^ anonymous case +caseBinder :: TyCoBinder -- ^ binder to scrutinize + -> (TyCoVarBinder -> a) -- ^ named case + -> (Type -> a) -- ^ anonymous case -> a caseBinder (Named v) f _ = f v caseBinder (Anon t) _ d = d t --- | Manufacture a new 'TyConBinder' from a 'TyBinder'. Anonymous --- 'TyBinder's are still assigned names as 'TyConBinder's, so we need --- the extra gunk with which to construct a 'Name'. Used when producing --- tyConTyVars from a datatype kind signature. Defined here to avoid module --- loops. -mkTyBinderTyConBinder :: TyBinder -> SrcSpan -> Unique -> OccName -> TyConBinder -mkTyBinderTyConBinder (Named (TvBndr tv argf)) _ _ _ = TvBndr tv (NamedTCB argf) -mkTyBinderTyConBinder (Anon kind) loc uniq occ - = TvBndr (mkTyVar (mkInternalName uniq occ loc) kind) AnonTCB {- %************************************************************************ @@ -1567,6 +1680,56 @@ But there are a number of complications: want to print it nicely in error messages. -} +-- | Split a type constructor application into its type constructor and +-- applied types. Note that this may fail in the case of a 'FunTy' with an +-- argument of unknown kind 'FunTy' (e.g. @FunTy (a :: k) Int@. since the kind +-- of @a@ isn't of the form @TYPE rep@). Consequently, you may need to zonk your +-- type before using this function. +-- +-- If you only need the 'TyCon', consider using 'tcTyConAppTyCon_maybe'. +tcSplitTyConApp_maybe :: HasCallStack => Type -> Maybe (TyCon, [Type]) +-- Defined here to avoid module loops between Unify and TcType. +tcSplitTyConApp_maybe ty | Just ty' <- tcView ty = tcSplitTyConApp_maybe ty' +tcSplitTyConApp_maybe ty = tcRepSplitTyConApp_maybe ty + +-- tcIsConstraintKind stuf only makes sense in the typechecker +-- After that Constraint = Type +-- See Note [coreView vs tcView] +-- Defined here because it is used in isPredTy and tcRepSplitAppTy_maybe (sigh) +tcIsConstraintKind :: Kind -> Bool +tcIsConstraintKind ty + | Just (tc, args) <- tcSplitTyConApp_maybe ty -- Note: tcSplit here + , isConstraintKindCon tc + = ASSERT2( null args, ppr ty ) True + + | otherwise + = False + +-- | Is this kind equivalent to @*@? +-- +-- This considers 'Constraint' to be distinct from @*@. For a version that +-- treats them as the same type, see 'isLiftedTypeKind'. +tcIsLiftedTypeKind :: Kind -> Bool +tcIsLiftedTypeKind ty + | Just (type_tc, [arg]) <- tcSplitTyConApp_maybe ty + , type_tc `hasKey` tYPETyConKey + , Just (lifted_rep_tc, args) <- tcSplitTyConApp_maybe arg + , lifted_rep_tc `hasKey` liftedRepDataConKey + = ASSERT2( null args, ppr ty ) True + | otherwise + = False + +tcReturnsConstraintKind :: Kind -> Bool +-- True <=> the Kind ultimately returns a Constraint +-- E.g. * -> Constraint +-- forall k. k -> Constraint +tcReturnsConstraintKind kind + | Just kind' <- tcView kind = tcReturnsConstraintKind kind' +tcReturnsConstraintKind (ForAllTy _ ty) = tcReturnsConstraintKind ty +tcReturnsConstraintKind (FunTy _ ty) = tcReturnsConstraintKind ty +tcReturnsConstraintKind (TyConApp tc _) = isConstraintKindCon tc +tcReturnsConstraintKind _ = False + -- | Is the type suitable to classify a given/wanted in the typechecker? isPredTy :: Type -> Bool -- See Note [isPredTy complications] @@ -1594,7 +1757,7 @@ isPredTy ty = go ty [] go_k :: Kind -> [KindOrType] -> Bool -- True <=> ('k' applied to 'kts') = Constraint - go_k k [] = isConstraintKind k + go_k k [] = tcIsConstraintKind k go_k k (arg:args) = case piResultTy_maybe k arg of Just k' -> go_k k' args Nothing -> WARN( True, text "isPredTy" <+> ppr ty ) @@ -1769,20 +1932,36 @@ eqRelRole :: EqRel -> Role eqRelRole NomEq = Nominal eqRelRole ReprEq = Representational -data PredTree = ClassPred Class [Type] - | EqPred EqRel Type Type - | IrredPred PredType +data PredTree + = ClassPred Class [Type] + | EqPred EqRel Type Type + | IrredPred PredType + | ForAllPred [TyCoVarBinder] [PredType] PredType + -- ForAllPred: see Note [Quantified constraints] in TcCanonical + -- NB: There is no TuplePred case + -- Tuple predicates like (Eq a, Ord b) are just treated + -- as ClassPred, as if we had a tuple class with two superclasses + -- class (c1, c2) => (%,%) c1 c2 classifyPredType :: PredType -> PredTree classifyPredType ev_ty = case splitTyConApp_maybe ev_ty of Just (tc, [_, _, ty1, ty2]) - | tc `hasKey` eqReprPrimTyConKey -> EqPred ReprEq ty1 ty2 - | tc `hasKey` eqPrimTyConKey -> EqPred NomEq ty1 ty2 + | tc `hasKey` eqReprPrimTyConKey -> EqPred ReprEq ty1 ty2 + | tc `hasKey` eqPrimTyConKey -> EqPred NomEq ty1 ty2 + Just (tc, tys) - | Just clas <- tyConClass_maybe tc -> ClassPred clas tys - _ -> IrredPred ev_ty + | Just clas <- tyConClass_maybe tc + -> ClassPred clas tys + + _ | (tvs, rho) <- splitForAllVarBndrs ev_ty + , (theta, pred) <- splitFunTys rho + , not (null tvs && null theta) + -> ForAllPred tvs theta pred -getClassPredTys :: PredType -> (Class, [Type]) + | otherwise + -> IrredPred ev_ty + +getClassPredTys :: HasDebugCallStack => PredType -> (Class, [Type]) getClassPredTys ty = case getClassPredTys_maybe ty of Just (clas, tys) -> (clas, tys) Nothing -> pprPanic "getClassPredTys" (ppr ty) @@ -1836,7 +2015,12 @@ predTypeEqRel ty -- -- This is a deterministic sorting operation -- (that is, doesn't depend on Uniques). -toposortTyVars :: [TyVar] -> [TyVar] +-- +-- It is also meant to be stable: that is, variables should not +-- be reordered unnecessarily. The implementation of this +-- has been observed to be stable, though it is not proven to +-- be so. See also Note [Ordering of implicit variables] in RnTypes +toposortTyVars :: [TyCoVar] -> [TyCoVar] toposortTyVars tvs = reverse $ [ node_payload node | node <- topologicalSortG $ graphFromEdgedVerticesOrd nodes ] @@ -1915,7 +2099,6 @@ pprSourceTyCon tycon | otherwise = ppr tycon --- @isTauTy@ tests if a type has no foralls isFamFreeTy :: Type -> Bool isFamFreeTy ty | Just ty' <- coreView ty = isFamFreeTy ty' isFamFreeTy (TyVarTy _) = True @@ -1940,7 +2123,7 @@ isFamFreeTy (CoercionTy _) = False -- Not sure about this -- levity polymorphic), and panics if the kind does not have the shape -- TYPE r. isLiftedType_maybe :: HasDebugCallStack => Type -> Maybe Bool -isLiftedType_maybe ty = go (getRuntimeRep "isLiftedType_maybe" ty) +isLiftedType_maybe ty = go (getRuntimeRep ty) where go rr | Just rr' <- coreView rr = go rr' go (TyConApp lifted_rep []) @@ -1960,6 +2143,19 @@ isUnliftedType ty = not (isLiftedType_maybe ty `orElse` pprPanic "isUnliftedType" (ppr ty <+> dcolon <+> ppr (typeKind ty))) +-- | Is this a type of kind RuntimeRep? (e.g. LiftedRep) +isRuntimeRepKindedTy :: Type -> Bool +isRuntimeRepKindedTy = isRuntimeRepTy . typeKind + +-- | Drops prefix of RuntimeRep constructors in 'TyConApp's. Useful for e.g. +-- dropping 'LiftedRep arguments of unboxed tuple TyCon applications: +-- +-- dropRuntimeRepArgs [ 'LiftedRep, 'IntRep +-- , String, Int# ] == [String, Int#] +-- +dropRuntimeRepArgs :: [Type] -> [Type] +dropRuntimeRepArgs = dropWhile isRuntimeRepKindedTy + -- | Extract the RuntimeRep classifier of a type. For instance, -- @getRuntimeRep_maybe Int = LiftedRep@. Returns 'Nothing' if this is not -- possible. @@ -1969,24 +2165,21 @@ getRuntimeRep_maybe = getRuntimeRepFromKind_maybe . typeKind -- | Extract the RuntimeRep classifier of a type. For instance, -- @getRuntimeRep_maybe Int = LiftedRep@. Panics if this is not possible. -getRuntimeRep :: HasDebugCallStack - => String -- ^ Printed in case of an error - -> Type -> Type -getRuntimeRep err ty = - case getRuntimeRep_maybe ty of +getRuntimeRep :: HasDebugCallStack => Type -> Type +getRuntimeRep ty + = case getRuntimeRep_maybe ty of Just r -> r - Nothing -> pprPanic "getRuntimeRep" - (text err $$ ppr ty <+> dcolon <+> ppr (typeKind ty)) + Nothing -> pprPanic "getRuntimeRep" (ppr ty <+> dcolon <+> ppr (typeKind ty)) -- | Extract the RuntimeRep classifier of a type from its kind. For example, -- @getRuntimeRepFromKind * = LiftedRep@; Panics if this is not possible. getRuntimeRepFromKind :: HasDebugCallStack - => String -> Type -> Type -getRuntimeRepFromKind err k = + => Type -> Type +getRuntimeRepFromKind k = case getRuntimeRepFromKind_maybe k of Just r -> r Nothing -> pprPanic "getRuntimeRepFromKind" - (text err $$ ppr k <+> dcolon <+> ppr (typeKind k)) + (ppr k <+> dcolon <+> ppr (typeKind k)) -- | Extract the RuntimeRep classifier of a type from its kind. For example, -- @getRuntimeRepFromKind * = LiftedRep@; Returns 'Nothing' if this is not @@ -2004,14 +2197,14 @@ getRuntimeRepFromKind_maybe = go isUnboxedTupleType :: Type -> Bool isUnboxedTupleType ty - = tyConAppTyCon (getRuntimeRep "isUnboxedTupleType" ty) `hasKey` tupleRepDataConKey + = tyConAppTyCon (getRuntimeRep ty) `hasKey` tupleRepDataConKey -- NB: Do not use typePrimRep, as that can't tell the difference between -- unboxed tuples and unboxed sums isUnboxedSumType :: Type -> Bool isUnboxedSumType ty - = tyConAppTyCon (getRuntimeRep "isUnboxedSumType" ty) `hasKey` sumRepDataConKey + = tyConAppTyCon (getRuntimeRep ty) `hasKey` sumRepDataConKey -- | See "Type#type_classification" for what an algebraic type is. -- Should only be applied to /types/, as opposed to e.g. partially @@ -2023,17 +2216,6 @@ isAlgType ty isAlgTyCon tc _other -> False --- | See "Type#type_classification" for what an algebraic type is. --- Should only be applied to /types/, as opposed to e.g. partially --- saturated type constructors. Closed type constructors are those --- with a fixed right hand side, as opposed to e.g. associated types -isClosedAlgType :: Type -> Bool -isClosedAlgType ty - = case splitTyConApp_maybe ty of - Just (tc, ty_args) | isAlgTyCon tc && not (isFamilyTyCon tc) - -> ASSERT2( ty_args `lengthIs` tyConArity tc, ppr ty ) True - _other -> False - -- | Check whether a type is a data family type isDataFamilyAppType :: Type -> Bool isDataFamilyAppType ty = case tyConAppTyCon_maybe ty of @@ -2090,7 +2272,39 @@ isValidJoinPointType arity ty | otherwise = False -{- +{- Note [Excess polymorphism and join points] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In principle, if a function would be a join point except that it fails +the polymorphism rule (see Note [The polymorphism rule of join points] in +CoreSyn), it can still be made a join point with some effort. This is because +all tail calls must return the same type (they return to the same context!), and +thus if the return type depends on an argument, that argument must always be the +same. + +For instance, consider: + + let f :: forall a. a -> Char -> [a] + f @a x c = ... f @a y 'a' ... + in ... f @Int 1 'b' ... f @Int 2 'c' ... + +(where the calls are tail calls). `f` fails the polymorphism rule because its +return type is [a], where [a] is bound. But since the type argument is always +'Int', we can rewrite it as: + + let f' :: Int -> Char -> [Int] + f' x c = ... f' y 'a' ... + in ... f' 1 'b' ... f 2 'c' ... + +and now we can make f' a join point: + + join f' :: Int -> Char -> [Int] + f' x c = ... jump f' y 'a' ... + in ... jump f' 1 'b' ... jump f' 2 'c' ... + +It's not clear that this comes up often, however. TODO: Measure how often and +add this analysis if necessary. See Trac #14620. + + ************************************************************************ * * \subsection{Sequencing on types} @@ -2104,7 +2318,7 @@ seqType (TyVarTy tv) = tv `seq` () seqType (AppTy t1 t2) = seqType t1 `seq` seqType t2 seqType (FunTy t1 t2) = seqType t1 `seq` seqType t2 seqType (TyConApp tc tys) = tc `seq` seqTypes tys -seqType (ForAllTy (TvBndr tv _) ty) = seqType (tyVarKind tv) `seq` seqType ty +seqType (ForAllTy (Bndr tv _) ty) = seqType (varType tv) `seq` seqType ty seqType (CastTy ty co) = seqType ty `seq` seqCo co seqType (CoercionTy co) = seqCo co @@ -2165,7 +2379,7 @@ eqVarBndrs :: RnEnv2 -> [Var] -> [Var] -> Maybe RnEnv2 eqVarBndrs env [] [] = Just env eqVarBndrs env (tv1:tvs1) (tv2:tvs2) - | eqTypeX env (tyVarKind tv1) (tyVarKind tv2) + | eqTypeX env (varType tv1) (varType tv2) = eqVarBndrs (rnBndr2 env tv1 tv2) tvs1 tvs2 eqVarBndrs _ _ _= Nothing @@ -2245,8 +2459,8 @@ nonDetCmpTypeX env orig_t1 orig_t2 = go env (TyVarTy tv1) (TyVarTy tv2) = liftOrdering $ rnOccL env tv1 `nonDetCmpVar` rnOccR env tv2 - go env (ForAllTy (TvBndr tv1 _) t1) (ForAllTy (TvBndr tv2 _) t2) - = go env (tyVarKind tv1) (tyVarKind tv2) + go env (ForAllTy (Bndr tv1 _) t1) (ForAllTy (Bndr tv2 _) t2) + = go env (varType tv1) (varType tv2) `thenCmpTy` go (rnBndr2 env tv1 tv2) t1 t2 -- See Note [Equality on AppTys] go env (AppTy s1 t1) ty2 @@ -2289,18 +2503,20 @@ nonDetCmpTypeX env orig_t1 orig_t2 = nonDetCmpTypesX :: RnEnv2 -> [Type] -> [Type] -> Ordering nonDetCmpTypesX _ [] [] = EQ nonDetCmpTypesX env (t1:tys1) (t2:tys2) = nonDetCmpTypeX env t1 t2 - `thenCmp` nonDetCmpTypesX env tys1 tys2 + `thenCmp` + nonDetCmpTypesX env tys1 tys2 nonDetCmpTypesX _ [] _ = LT nonDetCmpTypesX _ _ [] = GT ------------- --- | Compare two 'TyCon's. NB: This should /never/ see the "star synonyms", --- as recognized by Kind.isStarKindSynonymTyCon. See Note --- [Kind Constraint and kind *] in Kind. +-- | Compare two 'TyCon's. NB: This should /never/ see 'Constraint' (as +-- recognized by Kind.isConstraintKindCon) which is considered a synonym for +-- 'Type' in Core. +-- See Note [Kind Constraint and kind Type] in Kind. -- See Note [nonDetCmpType nondeterminism] nonDetCmpTc :: TyCon -> TyCon -> Ordering nonDetCmpTc tc1 tc2 - = ASSERT( not (isStarKindSynonymTyCon tc1) && not (isStarKindSynonymTyCon tc2) ) + = ASSERT( not (isConstraintKindCon tc1) && not (isConstraintKindCon tc2) ) u1 `nonDetCmpUnique` u2 where u1 = tyConUnique tc1 @@ -2314,16 +2530,34 @@ nonDetCmpTc tc1 tc2 ************************************************************************ -} -typeKind :: Type -> Kind -typeKind (TyConApp tc tys) = piResultTys (tyConKind tc) tys -typeKind (AppTy fun arg) = piResultTy (typeKind fun) arg -typeKind (LitTy l) = typeLiteralKind l -typeKind (FunTy {}) = liftedTypeKind -typeKind (ForAllTy _ ty) = typeKind ty -typeKind (TyVarTy tyvar) = tyVarKind tyvar -typeKind (CastTy _ty co) = pSnd $ coercionKind co -typeKind (CoercionTy co) = coercionType co - +typeKind :: HasDebugCallStack => Type -> Kind +typeKind (TyConApp tc tys) = piResultTys (tyConKind tc) tys +typeKind (AppTy fun arg) = typeKind_apps fun [arg] +typeKind (LitTy l) = typeLiteralKind l +typeKind (FunTy {}) = liftedTypeKind +typeKind (TyVarTy tyvar) = tyVarKind tyvar +typeKind (CastTy _ty co) = pSnd $ coercionKind co +typeKind (CoercionTy co) = coercionType co +typeKind ty@(ForAllTy (Bndr tv _) _) + | isTyVar tv -- See Note [Weird typing rule for ForAllTy]. + = case occCheckExpand tvs k of -- We must make sure tv does not occur in kind + Just k' -> k' -- As it is already out of scope! + Nothing -> pprPanic "typeKind" + (ppr ty $$ ppr k $$ ppr tvs $$ ppr body) + where + (tvs, body) = splitTyVarForAllTys ty + k = typeKind body +typeKind (ForAllTy {}) = liftedTypeKind + +typeKind_apps :: HasDebugCallStack => Type -> [Type] -> Kind +-- The sole purpose of the function is to accumulate +-- the type arugments, so we can call piResultTys, rather than +-- a succession of calls to piResultTy (which is asymptotically +-- less efficient as the number of arguments increases) +typeKind_apps (AppTy fun arg) args = typeKind_apps fun (arg:args) +typeKind_apps fun args = piResultTys (typeKind fun) args + +-------------------------- typeLiteralKind :: TyLit -> Kind typeLiteralKind l = case l of @@ -2354,6 +2588,160 @@ isTypeLevPoly = go resultIsLevPoly :: Type -> Bool resultIsLevPoly = isTypeLevPoly . snd . splitPiTys + +{- ********************************************************************** +* * + Occurs check expansion +%* * +%********************************************************************* -} + +{- Note [Occurs check expansion] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(occurCheckExpand tv xi) expands synonyms in xi just enough to get rid +of occurrences of tv outside type function arguments, if that is +possible; otherwise, it returns Nothing. + +For example, suppose we have + type F a b = [a] +Then + occCheckExpand b (F Int b) = Just [Int] +but + occCheckExpand a (F a Int) = Nothing + +We don't promise to do the absolute minimum amount of expanding +necessary, but we try not to do expansions we don't need to. We +prefer doing inner expansions first. For example, + type F a b = (a, Int, a, [a]) + type G b = Char +We have + occCheckExpand b (F (G b)) = Just (F Char) +even though we could also expand F to get rid of b. +-} + +occCheckExpand :: [Var] -> Type -> Maybe Type +-- See Note [Occurs check expansion] +-- We may have needed to do some type synonym unfolding in order to +-- get rid of the variable (or forall), so we also return the unfolded +-- version of the type, which is guaranteed to be syntactically free +-- of the given type variable. If the type is already syntactically +-- free of the variable, then the same type is returned. +occCheckExpand vs_to_avoid ty + = go (mkVarSet vs_to_avoid, emptyVarEnv) ty + where + go :: (VarSet, VarEnv TyCoVar) -> Type -> Maybe Type + -- The VarSet is the set of variables we are trying to avoid + -- The VarEnv carries mappings necessary + -- because of kind expansion + go cxt@(as, env) (TyVarTy tv') + | tv' `elemVarSet` as = Nothing + | Just tv'' <- lookupVarEnv env tv' = return (mkTyVarTy tv'') + | otherwise = do { tv'' <- go_var cxt tv' + ; return (mkTyVarTy tv'') } + + go _ ty@(LitTy {}) = return ty + go cxt (AppTy ty1 ty2) = do { ty1' <- go cxt ty1 + ; ty2' <- go cxt ty2 + ; return (mkAppTy ty1' ty2') } + go cxt (FunTy ty1 ty2) = do { ty1' <- go cxt ty1 + ; ty2' <- go cxt ty2 + ; return (mkFunTy ty1' ty2') } + go cxt@(as, env) (ForAllTy (Bndr tv vis) body_ty) + = do { ki' <- go cxt (varType tv) + ; let tv' = setVarType tv ki' + env' = extendVarEnv env tv tv' + as' = as `delVarSet` tv + ; body' <- go (as', env') body_ty + ; return (ForAllTy (Bndr tv' vis) body') } + + -- For a type constructor application, first try expanding away the + -- offending variable from the arguments. If that doesn't work, next + -- see if the type constructor is a type synonym, and if so, expand + -- it and try again. + go cxt ty@(TyConApp tc tys) + = case mapM (go cxt) tys of + Just tys' -> return (mkTyConApp tc tys') + Nothing | Just ty' <- tcView ty -> go cxt ty' + | otherwise -> Nothing + -- Failing that, try to expand a synonym + + go cxt (CastTy ty co) = do { ty' <- go cxt ty + ; co' <- go_co cxt co + ; return (mkCastTy ty' co') } + go cxt (CoercionTy co) = do { co' <- go_co cxt co + ; return (mkCoercionTy co') } + + ------------------ + go_var cxt v = do { k' <- go cxt (varType v) + ; return (setVarType v k') } + -- Works for TyVar and CoVar + -- See Note [Occurrence checking: look inside kinds] + + ------------------ + go_mco _ MRefl = return MRefl + go_mco ctx (MCo co) = MCo <$> go_co ctx co + + ------------------ + go_co cxt (Refl ty) = do { ty' <- go cxt ty + ; return (mkNomReflCo ty') } + go_co cxt (GRefl r ty mco) = do { mco' <- go_mco cxt mco + ; ty' <- go cxt ty + ; return (mkGReflCo r ty' mco') } + -- Note: Coercions do not contain type synonyms + go_co cxt (TyConAppCo r tc args) = do { args' <- mapM (go_co cxt) args + ; return (mkTyConAppCo r tc args') } + go_co cxt (AppCo co arg) = do { co' <- go_co cxt co + ; arg' <- go_co cxt arg + ; return (mkAppCo co' arg') } + go_co cxt@(as, env) (ForAllCo tv kind_co body_co) + = do { kind_co' <- go_co cxt kind_co + ; let tv' = setVarType tv $ + pFst (coercionKind kind_co') + env' = extendVarEnv env tv tv' + as' = as `delVarSet` tv + ; body' <- go_co (as', env') body_co + ; return (ForAllCo tv' kind_co' body') } + go_co cxt (FunCo r co1 co2) = do { co1' <- go_co cxt co1 + ; co2' <- go_co cxt co2 + ; return (mkFunCo r co1' co2') } + go_co cxt@(as,env) (CoVarCo c) + | c `elemVarSet` as = Nothing + | Just c' <- lookupVarEnv env c = return (mkCoVarCo c') + | otherwise = do { c' <- go_var cxt c + ; return (mkCoVarCo c') } + go_co cxt (HoleCo h) = do { c' <- go_var cxt (ch_co_var h) + ; return (HoleCo (h { ch_co_var = c' })) } + go_co cxt (AxiomInstCo ax ind args) = do { args' <- mapM (go_co cxt) args + ; return (mkAxiomInstCo ax ind args') } + go_co cxt (UnivCo p r ty1 ty2) = do { p' <- go_prov cxt p + ; ty1' <- go cxt ty1 + ; ty2' <- go cxt ty2 + ; return (mkUnivCo p' r ty1' ty2') } + go_co cxt (SymCo co) = do { co' <- go_co cxt co + ; return (mkSymCo co') } + go_co cxt (TransCo co1 co2) = do { co1' <- go_co cxt co1 + ; co2' <- go_co cxt co2 + ; return (mkTransCo co1' co2') } + go_co cxt (NthCo r n co) = do { co' <- go_co cxt co + ; return (mkNthCo r n co') } + go_co cxt (LRCo lr co) = do { co' <- go_co cxt co + ; return (mkLRCo lr co') } + go_co cxt (InstCo co arg) = do { co' <- go_co cxt co + ; arg' <- go_co cxt arg + ; return (mkInstCo co' arg') } + go_co cxt (KindCo co) = do { co' <- go_co cxt co + ; return (mkKindCo co') } + go_co cxt (SubCo co) = do { co' <- go_co cxt co + ; return (mkSubCo co') } + go_co cxt (AxiomRuleCo ax cs) = do { cs' <- mapM (go_co cxt) cs + ; return (mkAxiomRuleCo ax cs') } + + ------------------ + go_prov _ UnsafeCoerceProv = return UnsafeCoerceProv + go_prov cxt (PhantomProv co) = PhantomProv <$> go_co cxt co + go_prov cxt (ProofIrrelProv co) = ProofIrrelProv <$> go_co cxt co + go_prov _ p@(PluginProv _) = return p + + {- %************************************************************************ %* * @@ -2376,11 +2764,12 @@ tyConsOfType ty go (TyConApp tc tys) = go_tc tc `unionUniqSets` go_s tys go (AppTy a b) = go a `unionUniqSets` go b go (FunTy a b) = go a `unionUniqSets` go b `unionUniqSets` go_tc funTyCon - go (ForAllTy (TvBndr tv _) ty) = go ty `unionUniqSets` go (tyVarKind tv) + go (ForAllTy (Bndr tv _) ty) = go ty `unionUniqSets` go (varType tv) go (CastTy ty co) = go ty `unionUniqSets` go_co co go (CoercionTy co) = go_co co - go_co (Refl _ ty) = go ty + go_co (Refl ty) = go ty + go_co (GRefl _ ty mco) = go ty `unionUniqSets` go_mco mco go_co (TyConAppCo _ tc args) = go_tc tc `unionUniqSets` go_cos args go_co (AppCo co arg) = go_co co `unionUniqSets` go_co arg go_co (ForAllCo _ kind_co co) = go_co kind_co `unionUniqSets` go_co co @@ -2388,21 +2777,23 @@ tyConsOfType ty go_co (AxiomInstCo ax _ args) = go_ax ax `unionUniqSets` go_cos args go_co (UnivCo p _ t1 t2) = go_prov p `unionUniqSets` go t1 `unionUniqSets` go t2 go_co (CoVarCo {}) = emptyUniqSet + go_co (HoleCo {}) = emptyUniqSet go_co (SymCo co) = go_co co go_co (TransCo co1 co2) = go_co co1 `unionUniqSets` go_co co2 - go_co (NthCo _ co) = go_co co + go_co (NthCo _ _ co) = go_co co go_co (LRCo _ co) = go_co co go_co (InstCo co arg) = go_co co `unionUniqSets` go_co arg - go_co (CoherenceCo co1 co2) = go_co co1 `unionUniqSets` go_co co2 go_co (KindCo co) = go_co co go_co (SubCo co) = go_co co go_co (AxiomRuleCo _ cs) = go_cos cs + go_mco MRefl = emptyUniqSet + go_mco (MCo co) = go_co co + go_prov UnsafeCoerceProv = emptyUniqSet go_prov (PhantomProv co) = go_co co go_prov (ProofIrrelProv co) = go_co co go_prov (PluginProv _) = emptyUniqSet - go_prov (HoleProv _) = emptyUniqSet -- this last case can happen from the tyConsOfType used from -- checkTauTvUpdate @@ -2432,9 +2823,9 @@ splitVisVarsOfType orig_ty = Pair invis_vars vis_vars go (AppTy t1 t2) = go t1 `mappend` go t2 go (TyConApp tc tys) = go_tc tc tys go (FunTy t1 t2) = go t1 `mappend` go t2 - go (ForAllTy (TvBndr tv _) ty) + go (ForAllTy (Bndr tv _) ty) = ((`delVarSet` tv) <$> go ty) `mappend` - (invisible (tyCoVarsOfType $ tyVarKind tv)) + (invisible (tyCoVarsOfType $ varType tv)) go (LitTy {}) = mempty go (CastTy ty co) = go ty `mappend` invisible (tyCoVarsOfCo co) go (CoercionTy co) = invisible $ tyCoVarsOfCo co @@ -2458,7 +2849,7 @@ modifyJoinResTy orig_ar f orig_ty where go 0 ty = f ty go n ty | Just (arg_bndr, res_ty) <- splitPiTy_maybe ty - = mkPiTy arg_bndr (go (n-1) res_ty) + = mkTyCoPiTy arg_bndr (go (n-1) res_ty) | otherwise = pprPanic "modifyJoinResTy" (ppr orig_ar <+> ppr orig_ty) @@ -2469,3 +2860,20 @@ setJoinResTy :: Int -- Number of binders to skip -- INVARIANT: Same as for modifyJoinResTy setJoinResTy ar new_res_ty ty = modifyJoinResTy ar (const new_res_ty) ty + +{- +%************************************************************************ +%* * + Pretty-printing +%* * +%************************************************************************ + +Most pretty-printing is either in TyCoRep or IfaceType. + +-} + +-- | This variant preserves any use of TYPE in a type, effectively +-- locally setting -fprint-explicit-runtime-reps. +pprWithTYPE :: Type -> SDoc +pprWithTYPE ty = updSDocDynFlags (flip gopt_set Opt_PrintExplicitRuntimeReps) $ + ppr ty diff --git a/compiler/types/Type.hs-boot b/compiler/types/Type.hs-boot index 2fc251acb7..e5db1064d4 100644 --- a/compiler/types/Type.hs-boot +++ b/compiler/types/Type.hs-boot @@ -1,9 +1,11 @@ {-# LANGUAGE FlexibleContexts #-} module Type where + +import GhcPrelude import TyCon -import Var ( TyVar ) -import {-# SOURCE #-} TyCoRep( Type, Coercion, Kind ) +import Var ( TyCoVar ) +import {-# SOURCE #-} TyCoRep( Type, Coercion ) import Util isPredTy :: Type -> Bool @@ -11,16 +13,14 @@ isCoercionTy :: Type -> Bool mkAppTy :: Type -> Type -> Type mkCastTy :: Type -> Coercion -> Type -piResultTy :: Type -> Type -> Type +piResultTy :: HasDebugCallStack => Type -> Type -> Type -typeKind :: Type -> Kind eqType :: Type -> Type -> Bool -partitionInvisibles :: TyCon -> (a -> Type) -> [a] -> ([a], [a]) - coreView :: Type -> Maybe Type tcView :: Type -> Maybe Type -tyCoVarsOfTypesWellScoped :: [Type] -> [TyVar] -tyCoVarsOfTypeWellScoped :: Type -> [TyVar] +tyCoVarsOfTypesWellScoped :: [Type] -> [TyCoVar] +tyCoVarsOfTypeWellScoped :: Type -> [TyCoVar] +toposortTyVars :: [TyCoVar] -> [TyCoVar] splitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type]) diff --git a/compiler/types/Unify.hs b/compiler/types/Unify.hs index 79d0897a14..cfa10e4196 100644 --- a/compiler/types/Unify.hs +++ b/compiler/types/Unify.hs @@ -26,15 +26,17 @@ module Unify ( #include "HsVersions.h" +import GhcPrelude + import Var import VarEnv import VarSet -import Kind import Name( Name ) import Type hiding ( getTvSubstEnv ) import Coercion hiding ( getCvSubstEnv ) import TyCon import TyCoRep hiding ( getTvSubstEnv, getCvSubstEnv ) +import FV( FV, fvVarSet, fvVarList ) import Util import Pair import Outputable @@ -42,9 +44,7 @@ import UniqFM import UniqSet import Control.Monad -#if __GLASGOW_HASKELL__ > 710 import qualified Control.Monad.Fail as MonadFail -#endif import Control.Applicative hiding ( empty ) import qualified Control.Applicative @@ -70,6 +70,34 @@ Unification is much tricker than you might think. where x is the template type variable. Then we do not want to bind x to a/b! This is a kind of occurs check. The necessary locals accumulate in the RnEnv2. + +Note [tcMatchTy vs tcMatchTyKi] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This module offers two variants of matching: with kinds and without. +The TyKi variant takes two types, of potentially different kinds, +and matches them. Along the way, it necessarily also matches their +kinds. The Ty variant instead assumes that the kinds are already +eqType and so skips matching up the kinds. + +How do you choose between them? + +1. If you know that the kinds of the two types are eqType, use + the Ty variant. It is more efficient, as it does less work. + +2. If the kinds of variables in the template type might mention type families, + use the Ty variant (and do other work to make sure the kinds + work out). These pure unification functions do a straightforward + syntactic unification and do no complex reasoning about type + families. Note that the types of the variables in instances can indeed + mention type families, so instance lookup must use the Ty variant. + + (Nothing goes terribly wrong -- no panics -- if there might be type + families in kinds in the TyKi variant. You just might get match + failure even though a reducing a type family would lead to success.) + +3. Otherwise, if you're sure that the variable kinds do not mention + type families and you're not already sure that the kind of the template + equals the kind of the target, then use the TyKi version. -} -- | @tcMatchTy t1 t2@ produces a substitution (over fvs(t1)) @@ -83,15 +111,18 @@ Unification is much tricker than you might think. -- by the match, because tcMatchTy (and similar functions) are -- always used on top-level types, so we can bind any of the -- free variables of the LHS. +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTy :: Type -> Type -> Maybe TCvSubst tcMatchTy ty1 ty2 = tcMatchTys [ty1] [ty2] -- | Like 'tcMatchTy', but allows the kinds of the types to differ, -- and thus matches them as well. +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTyKi :: Type -> Type -> Maybe TCvSubst tcMatchTyKi ty1 ty2 = tcMatchTyKis [ty1] [ty2] -- | This is similar to 'tcMatchTy', but extends a substitution +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTyX :: TCvSubst -- ^ Substitution to extend -> Type -- ^ Template -> Type -- ^ Target @@ -99,6 +130,7 @@ tcMatchTyX :: TCvSubst -- ^ Substitution to extend tcMatchTyX subst ty1 ty2 = tcMatchTysX subst [ty1] [ty2] -- | Like 'tcMatchTy' but over a list of types. +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTys :: [Type] -- ^ Template -> [Type] -- ^ Target -> Maybe TCvSubst -- ^ One-shot; in principle the template @@ -109,6 +141,7 @@ tcMatchTys tys1 tys2 in_scope = mkInScopeSet (tyCoVarsOfTypes tys1 `unionVarSet` tyCoVarsOfTypes tys2) -- | Like 'tcMatchTyKi' but over a list of types. +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTyKis :: [Type] -- ^ Template -> [Type] -- ^ Target -> Maybe TCvSubst -- ^ One-shot substitution @@ -118,6 +151,7 @@ tcMatchTyKis tys1 tys2 in_scope = mkInScopeSet (tyCoVarsOfTypes tys1 `unionVarSet` tyCoVarsOfTypes tys2) -- | Like 'tcMatchTys', but extending a substitution +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTysX :: TCvSubst -- ^ Substitution to extend -> [Type] -- ^ Template -> [Type] -- ^ Target @@ -126,6 +160,7 @@ tcMatchTysX subst tys1 tys2 = tc_match_tys_x False subst tys1 tys2 -- | Like 'tcMatchTyKis', but extending a substitution +-- See also Note [tcMatchTy vs tcMatchTyKi] tcMatchTyKisX :: TCvSubst -- ^ Substitution to extend -> [Type] -- ^ Template -> [Type] -- ^ Target @@ -394,7 +429,7 @@ tcUnifyTyKis bind_fn tys1 tys2 type UnifyResult = UnifyResultM TCvSubst data UnifyResultM a = Unifiable a -- the subst that unifies the types | MaybeApart a -- the subst has as much as we know - -- it must be part of an most general unifier + -- it must be part of a most general unifier -- See Note [The substitution in MaybeApart] | SurelyApart deriving Functor @@ -463,6 +498,17 @@ tc_unify_tys :: (TyVar -> BindFlag) -> CvSubstEnv -> [Type] -> [Type] -> UnifyResultM (TvSubstEnv, CvSubstEnv) +-- NB: It's tempting to ASSERT here that, if we're not matching kinds, then +-- the kinds of the types should be the same. However, this doesn't work, +-- as the types may be a dependent telescope, where later types have kinds +-- that mention variables occurring earlier in the list of types. Here's an +-- example (from typecheck/should_fail/T12709): +-- template: [rep :: RuntimeRep, a :: TYPE rep] +-- target: [LiftedRep :: RuntimeRep, Int :: TYPE LiftedRep] +-- We can see that matching the first pair will make the kinds of the second +-- pair equal. Yet, we still don't need a separate pass to unify the kinds +-- of these types, so it's appropriate to use the Ty variant of unification. +-- See also Note [tcMatchTy vs tcMatchTyKi]. tc_unify_tys bind_fn unif inj_check match_kis rn_env tv_env cv_env tys1 tys2 = initUM tv_env cv_env $ do { when match_kis $ @@ -471,6 +517,7 @@ tc_unify_tys bind_fn unif inj_check match_kis rn_env tv_env cv_env tys1 tys2 ; (,) <$> getTvSubstEnv <*> getCvSubstEnv } where env = UMEnv { um_bind_fun = bind_fn + , um_skols = emptyVarSet , um_unif = unif , um_inj_tf = inj_check , um_rn_env = rn_env } @@ -499,7 +546,7 @@ During unification we use a TvSubstEnv/CvSubstEnv pair that is Note [Finding the substitution fixpoint] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Finding the fixpoint of a non-idempotent substitution arising from a -unification is harder than it looks, because of kinds. Consider +unification is much trickier than it looks, because of kinds. Consider T k (H k (f:k)) ~ T * (g:*) If we unify, we get the substitution [ k -> * @@ -514,41 +561,96 @@ If we don't do this, we may apply the substitution to something, and get an ill-formed type, i.e. one where typeKind will fail. This happened, for example, in Trac #9106. -This is the reason for extending env with [f:k -> f:*], in the -definition of env' in niFixTvSubst +It gets worse. In Trac #14164 we wanted to take the fixpoint of +this substitution + [ xs_asV :-> F a_aY6 (z_aY7 :: a_aY6) + (rest_aWF :: G a_aY6 (z_aY7 :: a_aY6)) + , a_aY6 :-> a_aXQ ] + +We have to apply the substitution for a_aY6 two levels deep inside +the invocation of F! We don't have a function that recursively +applies substitutions inside the kinds of variable occurrences (and +probably rightly so). + +So, we work as follows: + + 1. Start with the current substitution (which we are + trying to fixpoint + [ xs :-> F a (z :: a) (rest :: G a (z :: a)) + , a :-> b ] + + 2. Take all the free vars of the range of the substitution: + {a, z, rest, b} + NB: the free variable finder closes over + the kinds of variable occurrences + + 3. If none are in the domain of the substitution, stop. + We have found a fixpoint. + + 4. Remove the variables that are bound by the substitution, leaving + {z, rest, b} + + 5. Do a topo-sort to put them in dependency order: + [ b :: *, z :: a, rest :: G a z ] + + 6. Apply the substitution left-to-right to the kinds of these + tyvars, extending it each time with a new binding, so we + finish up with + [ xs :-> ..as before.. + , a :-> b + , b :-> b :: * + , z :-> z :: b + , rest :-> rest :: G b (z :: b) ] + Note that rest now has the right kind + + 7. Apply this extended substitution (once) to the range of + the /original/ substitution. (Note that we do the + extended substitution would go on forever if you tried + to find its fixpoint, because it maps z to z.) + + 8. And go back to step 1 + +In Step 6 we use the free vars from Step 2 as the initial +in-scope set, because all of those variables appear in the +range of the substitution, so they must all be in the in-scope +set. But NB that the type substitution engine does not look up +variables in the in-scope set; it is used only to ensure no +shadowing. -} niFixTCvSubst :: TvSubstEnv -> TCvSubst -- Find the idempotent fixed point of the non-idempotent substitution --- See Note [Finding the substitution fixpoint] +-- This is surprisingly tricky: +-- see Note [Finding the substitution fixpoint] -- ToDo: use laziness instead of iteration? -niFixTCvSubst tenv = f tenv +niFixTCvSubst tenv + | not_fixpoint = niFixTCvSubst (mapVarEnv (substTy subst) tenv) + | otherwise = subst where - f tenv - | not_fixpoint = f (mapVarEnv (substTy subst') tenv) - | otherwise = subst - where - not_fixpoint = anyVarSet in_domain range_tvs - in_domain tv = tv `elemVarEnv` tenv - - range_tvs = nonDetFoldUFM (unionVarSet . tyCoVarsOfType) emptyVarSet tenv - -- It's OK to use nonDetFoldUFM here because we - -- forget the order immediately by creating a set - subst = mkTvSubst (mkInScopeSet range_tvs) tenv - - -- env' extends env by replacing any free type with - -- that same tyvar with a substituted kind - -- See note [Finding the substitution fixpoint] - tenv' = extendVarEnvList tenv [ (rtv, mkTyVarTy $ - setTyVarKind rtv $ - substTy subst $ - tyVarKind rtv) - | rtv <- nonDetEltsUniqSet range_tvs - -- It's OK to use nonDetEltsUniqSet here - -- because we forget the order - -- immediatedly by putting it in VarEnv - , not (in_domain rtv) ] - subst' = mkTvSubst (mkInScopeSet range_tvs) tenv' + range_fvs :: FV + range_fvs = tyCoFVsOfTypes (nonDetEltsUFM tenv) + -- It's OK to use nonDetEltsUFM here because the + -- order of range_fvs, range_tvs is immaterial + + range_tvs :: [TyVar] + range_tvs = fvVarList range_fvs + + not_fixpoint = any in_domain range_tvs + in_domain tv = tv `elemVarEnv` tenv + + free_tvs = toposortTyVars (filterOut in_domain range_tvs) + + -- See Note [Finding the substitution fixpoint], Step 6 + init_in_scope = mkInScopeSet (fvVarSet range_fvs) + subst = foldl' add_free_tv + (mkTvSubst init_in_scope tenv) + free_tvs + + add_free_tv :: TCvSubst -> TyVar -> TCvSubst + add_free_tv subst tv + = extendTvSubst subst tv (mkTyVarTy tv') + where + tv' = updateTyVarKind (substTy subst) tv niSubstTvSet :: TvSubstEnv -> TyCoVarSet -> TyCoVarSet -- Apply the non-idempotent substitution to a set of type variables, @@ -711,7 +813,7 @@ Consider this: type instance Foo MkG = False We would like that to be accepted. For that to work, we need to introduce -a coercion variable on the left an then use it on the right. Accordingly, +a coercion variable on the left and then use it on the right. Accordingly, at use sites of Foo, we need to be able to use matching to figure out the value for the coercion. (See the desugared version: @@ -771,6 +873,41 @@ dependent/should_compile/KindEqualities2, we see, for example the constraint Num (Int |> (blah ; sym blah)). We naturally want to find a dictionary for that constraint, which requires dealing with coercions in this manner. + +Note [Matching in the presence of casts] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When matching, it is crucial that no variables from the template +end up in the range of the matching substitution (obviously!). +When unifying, that's not a constraint; instead we take the fixpoint +of the substitution at the end. + +So what should we do with this, when matching? + unify_ty (tmpl |> co) tgt kco + +Previously, wrongly, we pushed 'co' in the (horrid) accumulating +'kco' argument like this: + unify_ty (tmpl |> co) tgt kco + = unify_ty tmpl tgt (kco ; co) + +But that is obviously wrong because 'co' (from the template) ends +up in 'kco', which in turn ends up in the range of the substitution. + +This all came up in Trac #13910. Because we match tycon arguments +left-to-right, the ambient substitution will already have a matching +substitution for any kinds; so there is an easy fix: just apply +the substitution-so-far to the coercion from the LHS. + +Note that + +* When matching, the first arg of unify_ty is always the template; + we never swap round. + +* The above argument is distressingly indirect. We seek a + better way. + +* One better way is to ensure that type patterns (the template + in the matching process) have no casts. See Trac #14119. + -} -------------- unify_ty: the main workhorse ----------- @@ -780,7 +917,7 @@ type AmIUnifying = Bool -- True <=> Unifying unify_ty :: UMEnv -> Type -> Type -- Types to be unified and a co - -> Coercion -- A coercion between their kinds + -> CoercionN -- A coercion between their kinds -- See Note [Kind coercions in Unify] -> UM () -- See Note [Specification of unification] @@ -790,7 +927,12 @@ unify_ty env ty1 ty2 kco -- TODO: More commentary needed here | Just ty1' <- tcView ty1 = unify_ty env ty1' ty2 kco | Just ty2' <- tcView ty2 = unify_ty env ty1 ty2' kco - | CastTy ty1' co <- ty1 = unify_ty env ty1' ty2 (co `mkTransCo` kco) + | CastTy ty1' co <- ty1 = if um_unif env + then unify_ty env ty1' ty2 (co `mkTransCo` kco) + else -- See Note [Matching in the presence of casts] + do { subst <- getSubst env + ; let co' = substCo subst co + ; unify_ty env ty1' ty2 (co' `mkTransCo` kco) } | CastTy ty2' co <- ty2 = unify_ty env ty1 ty2' (kco `mkTransCo` mkSymCo co) unify_ty env (TyVarTy tv1) ty2 kco @@ -802,11 +944,11 @@ unify_ty env ty1 (TyVarTy tv2) kco unify_ty env ty1 ty2 _kco | Just (tc1, tys1) <- mb_tc_app1 , Just (tc2, tys2) <- mb_tc_app2 - , tc1 == tc2 || (tcIsStarKind ty1 && tcIsStarKind ty2) + , tc1 == tc2 || (tcIsLiftedTypeKind ty1 && tcIsLiftedTypeKind ty2) = if isInjectiveTyCon tc1 Nominal then unify_tys env tys1 tys2 else do { let inj | isTypeFamilyTyCon tc1 - = case familyTyConInjectivityInfo tc1 of + = case tyConInjectivityInfo tc1 of NotInjective -> repeat False Injective bs -> bs | otherwise @@ -853,8 +995,8 @@ unify_ty env ty1 (AppTy ty2a ty2b) _kco unify_ty _ (LitTy x) (LitTy y) _kco | x == y = return () -unify_ty env (ForAllTy (TvBndr tv1 _) ty1) (ForAllTy (TvBndr tv2 _) ty2) kco - = do { unify_ty env (tyVarKind tv1) (tyVarKind tv2) (mkNomReflCo liftedTypeKind) +unify_ty env (ForAllTy (Bndr tv1 _) ty1) (ForAllTy (Bndr tv2 _) ty2) kco + = do { unify_ty env (varType tv1) (varType tv2) (mkNomReflCo liftedTypeKind) ; let env' = umRnBndr2 env tv1 tv2 ; unify_ty env' ty1 ty2 kco } @@ -865,9 +1007,9 @@ unify_ty env (CoercionTy co1) (CoercionTy co2) kco CoVarCo cv | not (um_unif env) , not (cv `elemVarEnv` c_subst) - , BindMe <- tvBindFlagL env cv - -> do { checkRnEnvRCo env co2 - ; let (co_l, co_r) = decomposeFunCo kco + , BindMe <- tvBindFlag env cv + -> do { checkRnEnv env (tyCoVarsOfCo co2) + ; let (co_l, co_r) = decomposeFunCo Nominal kco -- cv :: t1 ~ t2 -- co2 :: s1 ~ s2 -- co_l :: t1 ~ s1 @@ -906,27 +1048,30 @@ unify_tys env orig_xs orig_ys --------------------------------- uVar :: UMEnv - -> TyVar -- Variable to be unified + -> InTyVar -- Variable to be unified -> Type -- with this Type -> Coercion -- :: kind tv ~N kind ty -> UM () uVar env tv1 ty kco - = do { -- Check to see whether tv1 is refined by the substitution - subst <- getTvSubstEnv - ; case (lookupVarEnv subst tv1) of - Just ty' | um_unif env -- Unifying, so - -> unify_ty env ty' ty kco -- call back into unify + = do { -- Apply the ambient renaming + let tv1' = umRnOccL env tv1 + + -- Check to see whether tv1 is refined by the substitution + ; subst <- getTvSubstEnv + ; case (lookupVarEnv subst tv1') of + Just ty' | um_unif env -- Unifying, so call + -> unify_ty env ty' ty kco -- back into unify | otherwise -> -- Matching, we don't want to just recur here. -- this is because the range of the subst is the target -- type, not the template type. So, just check for -- normal type equality. guard ((ty' `mkCastTy` kco) `eqType` ty) - Nothing -> uUnrefined env tv1 ty ty kco } -- No, continue + Nothing -> uUnrefined env tv1' ty ty kco } -- No, continue uUnrefined :: UMEnv - -> TyVar -- variable to be unified + -> OutTyVar -- variable to be unified -> Type -- with this Type -> Type -- (version w/ expanded synonyms) -> Coercion -- :: kind tv ~N kind ty @@ -934,36 +1079,35 @@ uUnrefined :: UMEnv -- We know that tv1 isn't refined -uUnrefined env tv1 ty2 ty2' kco +uUnrefined env tv1' ty2 ty2' kco | Just ty2'' <- coreView ty2' - = uUnrefined env tv1 ty2 ty2'' kco -- Unwrap synonyms + = uUnrefined env tv1' ty2 ty2'' kco -- Unwrap synonyms -- This is essential, in case we have -- type Foo a = a -- and then unify a ~ Foo a | TyVarTy tv2 <- ty2' - = do { let tv1' = umRnOccL env tv1 - tv2' = umRnOccR env tv2 + = do { let tv2' = umRnOccR env tv2 + ; unless (tv1' == tv2' && um_unif env) $ do + -- If we are unifying a ~ a, just return immediately + -- Do not extend the substitution -- See Note [Self-substitution when matching] - ; when (tv1' /= tv2' || not (um_unif env)) $ do - { subst <- getTvSubstEnv + -- Check to see whether tv2 is refined + { subst <- getTvSubstEnv ; case lookupVarEnv subst tv2 of - { Just ty' | um_unif env -> uUnrefined env tv1 ty' ty' kco - ; _ -> do - { -- So both are unrefined - - -- And then bind one or the other, - -- depending on which is bindable - ; let b1 = tvBindFlagL env tv1 - b2 = tvBindFlagR env tv2 - ty1 = mkTyVarTy tv1 + { Just ty' | um_unif env -> uUnrefined env tv1' ty' ty' kco + ; _ -> + + do { -- So both are unrefined + -- Bind one or the other, depending on which is bindable + ; let b1 = tvBindFlag env tv1' + b2 = tvBindFlag env tv2' + ty1 = mkTyVarTy tv1' ; case (b1, b2) of - (BindMe, _) -> do { checkRnEnvR env ty2 -- make sure ty2 is not a local - ; extendTvEnv tv1 (ty2 `mkCastTy` mkSymCo kco) } + (BindMe, _) -> bindTv env tv1' (ty2 `mkCastTy` mkSymCo kco) (_, BindMe) | um_unif env - -> do { checkRnEnvL env ty1 -- ditto for ty1 - ; extendTvEnv tv2 (ty1 `mkCastTy` kco) } + -> bindTv (umSwapRn env) tv2 (ty1 `mkCastTy` kco) _ | tv1' == tv2' -> return () -- How could this happen? If we're only matching and if @@ -972,25 +1116,37 @@ uUnrefined env tv1 ty2 ty2' kco _ -> maybeApart -- See Note [Unification with skolems] }}}} -uUnrefined env tv1 ty2 ty2' kco -- ty2 is not a type variable - = do { occurs <- elemNiSubstSet tv1 (tyCoVarsOfType ty2') - ; if um_unif env && occurs -- See Note [Self-substitution when matching] - then maybeApart -- Occurs check, see Note [Fine-grained unification] - else do bindTv env tv1 (ty2 `mkCastTy` mkSymCo kco) } - -- Bind tyvar to the synonym if poss +uUnrefined env tv1' ty2 _ kco -- ty2 is not a type variable + = case tvBindFlag env tv1' of + Skolem -> maybeApart -- See Note [Unification with skolems] + BindMe -> bindTv env tv1' (ty2 `mkCastTy` mkSymCo kco) + +bindTv :: UMEnv -> OutTyVar -> Type -> UM () +-- OK, so we want to extend the substitution with tv := ty +-- But first, we must do a couple of checks +bindTv env tv1 ty2 + = do { let free_tvs2 = tyCoVarsOfType ty2 + + -- Make sure tys mentions no local variables + -- E.g. (forall a. b) ~ (forall a. [a]) + -- We should not unify b := [a]! + ; checkRnEnv env free_tvs2 -elemNiSubstSet :: TyVar -> TyCoVarSet -> UM Bool -elemNiSubstSet v set + -- Occurs check, see Note [Fine-grained unification] + -- Make sure you include 'kco' (which ty2 does) Trac #14846 + ; occurs <- occursCheck env tv1 free_tvs2 + + ; if occurs then maybeApart + else extendTvEnv tv1 ty2 } + +occursCheck :: UMEnv -> TyVar -> VarSet -> UM Bool +occursCheck env tv free_tvs + | um_unif env = do { tsubst <- getTvSubstEnv - ; return $ v `elemVarSet` niSubstTvSet tsubst set } + ; return (tv `elemVarSet` niSubstTvSet tsubst free_tvs) } -bindTv :: UMEnv -> TyVar -> Type -> UM () -bindTv env tv ty -- ty is not a variable - = do { checkRnEnvR env ty -- make sure ty mentions no local variables - ; case tvBindFlagL env tv of - Skolem -> maybeApart -- See Note [Unification with skolems] - BindMe -> extendTvEnv tv ty - } + | otherwise -- Matching; no occurs check + = return False -- See Note [Self-substitution when matching] {- %************************************************************************ @@ -1015,12 +1171,27 @@ data BindFlag ************************************************************************ -} -data UMEnv = UMEnv { um_bind_fun :: TyVar -> BindFlag - -- User-supplied BindFlag function - , um_unif :: AmIUnifying - , um_inj_tf :: Bool -- Checking for injectivity? - -- See (end of) Note [Specification of unification] - , um_rn_env :: RnEnv2 } +data UMEnv + = UMEnv { um_unif :: AmIUnifying + + , um_inj_tf :: Bool + -- Checking for injectivity? + -- See (end of) Note [Specification of unification] + + , um_rn_env :: RnEnv2 + -- Renaming InTyVars to OutTyVars; this eliminates + -- shadowing, and lines up matching foralls on the left + -- and right + + , um_skols :: TyVarSet + -- OutTyVars bound by a forall in this unification; + -- Do not bind these in the substitution! + -- See the function tvBindFlag + + , um_bind_fun :: TyVar -> BindFlag + -- User-supplied BindFlag function, + -- for variables not in um_skols + } data UMState = UMState { um_tv_env :: TvSubstEnv @@ -1036,7 +1207,7 @@ instance Applicative UM where (<*>) = ap instance Monad UM where - fail _ = UM (\_ -> SurelyApart) -- failed pattern match + fail = MonadFail.fail m >>= k = UM (\state -> do { (state', v) <- unUM m state ; unUM (k v) state' }) @@ -1050,10 +1221,8 @@ instance Alternative UM where instance MonadPlus UM -#if __GLASGOW_HASKELL__ > 710 instance MonadFail.MonadFail UM where fail _ = UM (\_ -> SurelyApart) -- failed pattern match -#endif initUM :: TvSubstEnv -- subst to extend -> CvSubstEnv @@ -1067,15 +1236,10 @@ initUM subst_env cv_subst_env um state = UMState { um_tv_env = subst_env , um_cv_env = cv_subst_env } -tvBindFlagL :: UMEnv -> TyVar -> BindFlag -tvBindFlagL env tv - | inRnEnvL (um_rn_env env) tv = Skolem - | otherwise = um_bind_fun env tv - -tvBindFlagR :: UMEnv -> TyVar -> BindFlag -tvBindFlagR env tv - | inRnEnvR (um_rn_env env) tv = Skolem - | otherwise = um_bind_fun env tv +tvBindFlag :: UMEnv -> OutTyVar -> BindFlag +tvBindFlag env tv + | tv `elemVarSet` um_skols env = Skolem + | otherwise = um_bind_fun env tv getTvSubstEnv :: UM TvSubstEnv getTvSubstEnv = UM $ \state -> Unifiable (state, um_tv_env state) @@ -1083,6 +1247,12 @@ getTvSubstEnv = UM $ \state -> Unifiable (state, um_tv_env state) getCvSubstEnv :: UM CvSubstEnv getCvSubstEnv = UM $ \state -> Unifiable (state, um_cv_env state) +getSubst :: UMEnv -> UM TCvSubst +getSubst env = do { tv_env <- getTvSubstEnv + ; cv_env <- getCvSubstEnv + ; let in_scope = rnInScopeSet (um_rn_env env) + ; return (mkTCvSubst in_scope (tv_env, cv_env)) } + extendTvEnv :: TyVar -> Type -> UM () extendTvEnv tv ty = UM $ \state -> Unifiable (state { um_tv_env = extendVarEnv (um_tv_env state) tv ty }, ()) @@ -1093,17 +1263,22 @@ extendCvEnv cv co = UM $ \state -> umRnBndr2 :: UMEnv -> TyCoVar -> TyCoVar -> UMEnv umRnBndr2 env v1 v2 - = env { um_rn_env = rnBndr2 (um_rn_env env) v1 v2 } - -checkRnEnv :: (RnEnv2 -> VarEnv Var) -> UMEnv -> VarSet -> UM () -checkRnEnv get_set env varset = UM $ \ state -> - let env_vars = get_set (um_rn_env env) in - if isEmptyVarEnv env_vars || (getUniqSet varset `disjointVarEnv` env_vars) - -- NB: That isEmptyVarSet is a critical optimization; it - -- means we don't have to calculate the free vars of - -- the type, often saving quite a bit of allocation. - then Unifiable (state, ()) - else MaybeApart (state, ()) + = env { um_rn_env = rn_env', um_skols = um_skols env `extendVarSet` v' } + where + (rn_env', v') = rnBndr2_var (um_rn_env env) v1 v2 + +checkRnEnv :: UMEnv -> VarSet -> UM () +checkRnEnv env varset + | isEmptyVarSet skol_vars = return () + | varset `disjointVarSet` skol_vars = return () + | otherwise = maybeApart + -- ToDo: why MaybeApart? + -- I think SurelyApart would be right + where + skol_vars = um_skols env + -- NB: That isEmptyVarSet guard is a critical optimization; + -- it means we don't have to calculate the free vars of + -- the type, often saving quite a bit of allocation. -- | Converts any SurelyApart to a MaybeApart don'tBeSoSure :: UM () -> UM () @@ -1112,15 +1287,6 @@ don'tBeSoSure um = UM $ \ state -> SurelyApart -> MaybeApart (state, ()) other -> other -checkRnEnvR :: UMEnv -> Type -> UM () -checkRnEnvR env ty = checkRnEnv rnEnvR env (tyCoVarsOfType ty) - -checkRnEnvL :: UMEnv -> Type -> UM () -checkRnEnvL env ty = checkRnEnv rnEnvL env (tyCoVarsOfType ty) - -checkRnEnvRCo :: UMEnv -> Coercion -> UM () -checkRnEnvRCo env co = checkRnEnv rnEnvR env (tyCoVarsOfCo co) - umRnOccL :: UMEnv -> TyVar -> TyVar umRnOccL env v = rnOccL (um_rn_env env) v @@ -1152,7 +1318,7 @@ data MatchEnv = ME { me_tmpls :: TyVarSet , me_env :: RnEnv2 } -- | 'liftCoMatch' is sort of inverse to 'liftCoSubst'. In particular, if --- @liftCoMatch vars ty co == Just s@, then @listCoSubst s ty == co@, +-- @liftCoMatch vars ty co == Just s@, then @liftCoSubst s ty == co@, -- where @==@ there means that the result of 'liftCoSubst' has the same -- type as the original co; but may be different under the hood. -- That is, it matches a type against a coercion of the same @@ -1217,10 +1383,13 @@ ty_co_match menv subst ty co lkco rkco ty_co_match menv subst ty co lkco rkco | CastTy ty' co' <- ty - = ty_co_match menv subst ty' co (co' `mkTransCo` lkco) (co' `mkTransCo` rkco) - - | CoherenceCo co1 co2 <- co - = ty_co_match menv subst ty co1 (lkco `mkTransCo` mkSymCo co2) rkco + -- See Note [Matching in the presence of casts] + = let empty_subst = mkEmptyTCvSubst (rnInScopeSet (me_env menv)) + substed_co_l = substCo (liftEnvSubstLeft empty_subst subst) co' + substed_co_r = substCo (liftEnvSubstRight empty_subst subst) co' + in + ty_co_match menv subst ty' co (substed_co_l `mkTransCo` lkco) + (substed_co_r `mkTransCo` rkco) | SymCo co' <- co = swapLiftCoEnv <$> ty_co_match menv (swapLiftCoEnv subst) ty co' rkco lkco @@ -1236,7 +1405,7 @@ ty_co_match menv subst (TyVarTy tv1) co lkco rkco = if any (inRnEnvR rn_env) (tyCoVarsOfCoList co) then Nothing -- occurs check failed else Just $ extendVarEnv subst tv1' $ - castCoercionKind co (mkSymCo lkco) (mkSymCo rkco) + castCoercionKindI co (mkSymCo lkco) (mkSymCo rkco) | otherwise = Nothing @@ -1269,9 +1438,10 @@ ty_co_match menv subst (FunTy ty1 ty2) co _lkco _rkco = let Pair lkcos rkcos = traverse (fmap mkNomReflCo . coercionKind) [co1,co2] in ty_co_match_args menv subst [ty1, ty2] [co1, co2] lkcos rkcos -ty_co_match menv subst (ForAllTy (TvBndr tv1 _) ty1) +ty_co_match menv subst (ForAllTy (Bndr tv1 _) ty1) (ForAllCo tv2 kind_co2 co2) lkco rkco + | isTyVar tv1 && isTyVar tv2 = do { subst1 <- ty_co_match menv subst (tyVarKind tv1) kind_co2 ki_ki_co ki_ki_co ; let rn_env0 = me_env menv @@ -1281,9 +1451,47 @@ ty_co_match menv subst (ForAllTy (TvBndr tv1 _) ty1) where ki_ki_co = mkNomReflCo liftedTypeKind +-- ty_co_match menv subst (ForAllTy (Bndr cv1 _) ty1) +-- (ForAllCo cv2 kind_co2 co2) +-- lkco rkco +-- | isCoVar cv1 && isCoVar cv2 +-- We seems not to have enough information for this case +-- 1. Given: +-- cv1 :: (s1 :: k1) ~r (s2 :: k2) +-- kind_co2 :: (s1' ~ s2') ~N (t1 ~ t2) +-- eta1 = mkNthCo role 2 (downgradeRole r Nominal kind_co2) +-- :: s1' ~ t1 +-- eta2 = mkNthCo role 3 (downgradeRole r Nominal kind_co2) +-- :: s2' ~ t2 +-- Wanted: +-- subst1 <- ty_co_match menv subst s1 eta1 kco1 kco2 +-- subst2 <- ty_co_match menv subst1 s2 eta2 kco3 kco4 +-- Question: How do we get kcoi? +-- 2. Given: +-- lkco :: <*> -- See Note [Weird typing rule for ForAllTy] in Type +-- rkco :: <*> +-- Wanted: +-- ty_co_match menv' subst2 ty1 co2 lkco' rkco' +-- Question: How do we get lkco' and rkco'? + ty_co_match _ subst (CoercionTy {}) _ _ _ = Just subst -- don't inspect coercions +ty_co_match menv subst ty (GRefl r t (MCo co)) lkco rkco + = ty_co_match menv subst ty (GRefl r t MRefl) lkco (rkco `mkTransCo` mkSymCo co) + +ty_co_match menv subst ty co1 lkco rkco + | Just (CastTy t co, r) <- isReflCo_maybe co1 + -- In @pushRefl@, pushing reflexive coercion inside CastTy will give us + -- t |> co ~ t ; <t> ; t ~ t |> co + -- But transitive coercions are not helpful. Therefore we deal + -- with it here: we do recursion on the smaller reflexive coercion, + -- while propagating the correct kind coercions. + = let kco' = mkSymCo co + in ty_co_match menv subst ty (mkReflCo r t) (lkco `mkTransCo` kco') + (rkco `mkTransCo` kco') + + ty_co_match menv subst ty co lkco rkco | Just co' <- pushRefl co = ty_co_match menv subst ty co' lkco rkco | otherwise = Nothing @@ -1328,17 +1536,18 @@ ty_co_match_args menv subst (ty:tys) (arg:args) (lkco:lkcos) (rkco:rkcos) ty_co_match_args _ _ _ _ _ _ = Nothing pushRefl :: Coercion -> Maybe Coercion -pushRefl (Refl Nominal (AppTy ty1 ty2)) - = Just (AppCo (Refl Nominal ty1) (mkNomReflCo ty2)) -pushRefl (Refl r (FunTy ty1 ty2)) - | Just rep1 <- getRuntimeRep_maybe ty1 - , Just rep2 <- getRuntimeRep_maybe ty2 - = Just (TyConAppCo r funTyCon [ mkReflCo r rep1, mkReflCo r rep2 - , mkReflCo r ty1, mkReflCo r ty2 ]) -pushRefl (Refl r (TyConApp tc tys)) - = Just (TyConAppCo r tc (zipWith mkReflCo (tyConRolesX r tc) tys)) -pushRefl (Refl r (ForAllTy (TvBndr tv _) ty)) - = Just (mkHomoForAllCos_NoRefl [tv] (Refl r ty)) +pushRefl co = + case (isReflCo_maybe co) of + Just (AppTy ty1 ty2, Nominal) + -> Just (AppCo (mkReflCo Nominal ty1) (mkNomReflCo ty2)) + Just (FunTy ty1 ty2, r) + | Just rep1 <- getRuntimeRep_maybe ty1 + , Just rep2 <- getRuntimeRep_maybe ty2 + -> Just (TyConAppCo r funTyCon [ mkReflCo r rep1, mkReflCo r rep2 + , mkReflCo r ty1, mkReflCo r ty2 ]) + Just (TyConApp tc tys, r) + -> Just (TyConAppCo r tc (zipWith mkReflCo (tyConRolesX r tc) tys)) + Just (ForAllTy (Bndr tv _) ty, r) + -> Just (ForAllCo tv (mkNomReflCo (varType tv)) (mkReflCo r ty)) -- NB: NoRefl variant. Otherwise, we get a loop! -pushRefl (Refl r (CastTy ty co)) = Just (castCoercionKind (Refl r ty) co co) -pushRefl _ = Nothing + _ -> Nothing |