X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypes%2FType.lhs;h=eb159f7d022bb37a4493f8fb60ae5218329a4d14;hb=1181f398e73359a2e6387364b4fe270d4cc78f36;hp=5888c27bcad8c0665deba489c60a7e3ecba248f9;hpb=8f7ac3fe40d3d55743b824deab655d0797a1c55f;p=ghc-hetmet.git diff --git a/ghc/compiler/types/Type.lhs b/ghc/compiler/types/Type.lhs index 5888c27..eb159f7 100644 --- a/ghc/compiler/types/Type.lhs +++ b/ghc/compiler/types/Type.lhs @@ -1,932 +1,991 @@ -\begin{code} -#include "HsVersions.h" +% +% (c) The GRASP/AQUA Project, Glasgow University, 1998 +% +\section[Type]{Type - public interface} +\begin{code} module Type ( - GenType(..), SYN_IE(Type), SYN_IE(TauType), - mkTyVarTy, mkTyVarTys, - getTyVar, getTyVar_maybe, isTyVarTy, - mkAppTy, mkAppTys, splitAppTy, - mkFunTy, mkFunTys, - splitFunTy, splitFunTyExpandingDicts, splitFunTyExpandingDictsAndPeeking, - getFunTy_maybe, getFunTyExpandingDicts_maybe, - mkTyConTy, getTyCon_maybe, applyTyCon, - mkSynTy, - mkForAllTy, mkForAllTys, getForAllTy_maybe, getForAllTyExpandingDicts_maybe, splitForAllTy, - mkForAllUsageTy, getForAllUsageTy, - applyTy, -#ifdef DEBUG - expandTy, -- only let out for debugging (ToDo: rm?) -#endif - isPrimType, isUnboxedType, typePrimRep, + -- re-exports from TypeRep: + Type, PredType, TauType, ThetaType, + Kind, TyVarSubst, + + superKind, superBoxity, -- KX and BX respectively + liftedBoxity, unliftedBoxity, -- :: BX + openKindCon, -- :: KX + typeCon, -- :: BX -> KX + liftedTypeKind, unliftedTypeKind, openTypeKind, -- :: KX + mkArrowKind, mkArrowKinds, -- :: KX -> KX -> KX + isTypeKind, + funTyCon, + + usageKindCon, -- :: KX + usageTypeKind, -- :: KX + usOnceTyCon, usManyTyCon, -- :: $ + usOnce, usMany, -- :: $ + + -- exports from this module: + hasMoreBoxityInfo, defaultKind, + + mkTyVarTy, mkTyVarTys, getTyVar, getTyVar_maybe, isTyVarTy, + + mkAppTy, mkAppTys, splitAppTy, splitAppTys, splitAppTy_maybe, + + mkFunTy, mkFunTys, splitFunTy, splitFunTy_maybe, splitFunTys, + funResultTy, funArgTy, zipFunTys, - SYN_IE(RhoType), SYN_IE(SigmaType), SYN_IE(ThetaType), - mkDictTy, - mkRhoTy, splitRhoTy, mkTheta, isDictTy, - mkSigmaTy, splitSigmaTy, + mkTyConApp, mkTyConTy, + tyConAppTyCon, tyConAppArgs, + splitTyConApp_maybe, splitTyConApp, - maybeAppTyCon, getAppTyCon, - maybeAppDataTyCon, getAppDataTyCon, getAppSpecDataTyCon, - maybeAppDataTyConExpandingDicts, maybeAppSpecDataTyConExpandingDicts, - getAppDataTyConExpandingDicts, getAppSpecDataTyConExpandingDicts, - maybeBoxedPrimType, + mkUTy, splitUTy, splitUTy_maybe, + isUTy, uaUTy, unUTy, liftUTy, mkUTyM, + isUsageKind, isUsage, isUTyVar, - matchTy, matchTys, eqTy, eqSimpleTy, eqSimpleTheta, + mkSynTy, - instantiateTy, instantiateTauTy, instantiateUsage, - applyTypeEnvToTy, + repType, splitRepFunTys, typePrimRep, - isTauTy, + mkForAllTy, mkForAllTys, splitForAllTy_maybe, splitForAllTys, + applyTy, applyTys, isForAllTy, + + -- Source types + SourceType(..), sourceTypeRep, mkPredTy, mkPredTys, + + -- Newtypes + splitNewType_maybe, + + -- Lifting and boxity + isUnLiftedType, isUnboxedTupleType, isAlgType, isStrictType, isPrimitiveType, + + -- Free variables + tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tyVarsOfTheta, + usageAnnOfType, typeKind, addFreeTyVars, + + -- Tidying up for printing + tidyType, tidyTypes, + tidyOpenType, tidyOpenTypes, + tidyTyVarBndr, tidyFreeTyVars, + tidyOpenTyVar, tidyOpenTyVars, + tidyTopType, tidyPred, + + -- Comparison + eqType, eqKind, eqUsage, + + -- Seq + seqType, seqTypes - tyVarsOfType, tyVarsOfTypes, namesOfType, typeKind ) where -IMP_Ubiq() ---IMPORT_DELOOPER(IdLoop) -- for paranoia checking -IMPORT_DELOOPER(TyLoop) ---IMPORT_DELOOPER(PrelLoop) -- for paranoia checking +#include "HsVersions.h" + +-- We import the representation and primitive functions from TypeRep. +-- Many things are reexported, but not the representation! + +import TypeRep + +-- Other imports: + +import {-# SOURCE #-} PprType( pprType ) -- Only called in debug messages +import {-# SOURCE #-} Subst ( substTyWith ) -- friends: -import Class ( classSig, classOpLocalType, GenClass{-instances-} ) -import Kind ( mkBoxedTypeKind, resultKind, notArrowKind, Kind ) -import TyCon ( mkFunTyCon, isFunTyCon, - isPrimTyCon, isDataTyCon, isSynTyCon, maybeNewTyCon, isNewTyCon, - tyConKind, tyConDataCons, getSynTyConDefn, TyCon ) -import TyVar ( tyVarKind, GenTyVar{-instances-}, SYN_IE(GenTyVarSet), - emptyTyVarSet, unionTyVarSets, minusTyVarSet, - unitTyVarSet, nullTyVarEnv, lookupTyVarEnv, delFromTyVarEnv, - addOneToTyVarEnv, SYN_IE(TyVarEnv), SYN_IE(TyVar) ) -import Usage ( usageOmega, GenUsage, SYN_IE(Usage), SYN_IE(UVar), SYN_IE(UVarEnv), - nullUVarEnv, addOneToUVarEnv, lookupUVarEnv, eqUVar, - eqUsage ) - -import Name ( NamedThing(..), - NameSet(..), unionNameSets, emptyNameSet, unitNameSet, minusNameSet +import Var ( Var, TyVar, tyVarKind, tyVarName, setTyVarName ) +import VarEnv +import VarSet + +import Name ( NamedThing(..), mkLocalName, tidyOccName ) +import Class ( classTyCon ) +import TyCon ( TyCon, isRecursiveTyCon, isPrimTyCon, + isUnboxedTupleTyCon, isUnLiftedTyCon, + isFunTyCon, isNewTyCon, newTyConRep, + isAlgTyCon, isSynTyCon, tyConArity, + tyConKind, getSynTyConDefn, + tyConPrimRep, ) -- others -import Maybes ( maybeToBool, assocMaybe ) -import PrimRep ( PrimRep(..) ) -import Unique -- quite a few *Keys -import Util ( thenCmp, zipEqual, assoc, - panic, panic#, assertPanic, pprPanic, - Ord3(..){-instances-} - ) --- ToDo:rm all these ---import {-mumble-} --- Pretty ---import {-mumble-} --- PprStyle ---import {-mumble-} --- PprType --(pprType ) ---import {-mumble-} --- UniqFM (ufmToList ) ---import {-mumble-} --- Outputable ---import PprEnv +import CmdLineOpts ( opt_DictsStrict ) +import Maybes ( maybeToBool ) +import SrcLoc ( noSrcLoc ) +import PrimRep ( PrimRep(..) ) +import Unique ( Uniquable(..) ) +import Util ( mapAccumL, seqList ) +import Outputable +import UniqSet ( sizeUniqSet ) -- Should come via VarSet \end{code} -Data types -~~~~~~~~~~ -\begin{code} -type Type = GenType TyVar UVar -- Used after typechecker - -data GenType tyvar uvar -- Parameterised over type and usage variables - = TyVarTy tyvar - - | AppTy - (GenType tyvar uvar) - (GenType tyvar uvar) - - | TyConTy -- Constants of a specified kind - TyCon -- Must *not* be a SynTyCon - (GenUsage uvar) -- Usage gives uvar of the full application, - -- iff the full application is of kind Type - -- c.f. the Usage field in TyVars - - | SynTy -- Synonyms must be saturated, and contain their expansion - TyCon -- Must be a SynTyCon - [GenType tyvar uvar] - (GenType tyvar uvar) -- Expansion! - - | ForAllTy - tyvar - (GenType tyvar uvar) -- TypeKind - - | ForAllUsageTy - uvar -- Quantify over this - [uvar] -- Bounds; the quantified var must be - -- less than or equal to all these - (GenType tyvar uvar) - - -- Two special cases that save a *lot* of administrative - -- overhead: - - | FunTy -- BoxedTypeKind - (GenType tyvar uvar) -- Both args are of TypeKind - (GenType tyvar uvar) - (GenUsage uvar) - - | DictTy -- TypeKind - Class -- Class - (GenType tyvar uvar) -- Arg has kind TypeKind - (GenUsage uvar) -\end{code} +%************************************************************************ +%* * +\subsection{Stuff to do with kinds.} +%* * +%************************************************************************ \begin{code} -type RhoType = Type -type TauType = Type -type ThetaType = [(Class, Type)] -type SigmaType = Type +hasMoreBoxityInfo :: Kind -> Kind -> Bool +hasMoreBoxityInfo k1 k2 + | k2 `eqKind` openTypeKind = True + | otherwise = k1 `eqType` k2 + +defaultKind :: Kind -> Kind +-- Used when generalising: default kind '?' to '*' +defaultKind kind | kind `eqKind` openTypeKind = liftedTypeKind + | otherwise = kind + +isTypeKind :: Kind -> Bool +-- True of kind * and *# +isTypeKind k = case splitTyConApp_maybe k of + Just (tc,[k]) -> tc == typeCon + other -> False \end{code} -Expand abbreviations -~~~~~~~~~~~~~~~~~~~~ -Removes just the top level of any abbreviations. +%************************************************************************ +%* * +\subsection{Constructor-specific functions} +%* * +%************************************************************************ -\begin{code} -expandTy :: Type -> Type -- Restricted to Type due to Dict expansion -expandTy (FunTy t1 t2 u) = AppTy (AppTy (TyConTy mkFunTyCon u) t1) t2 -expandTy (SynTy _ _ t) = expandTy t -expandTy (DictTy clas ty u) - = case all_arg_tys of +--------------------------------------------------------------------- + TyVarTy + ~~~~~~~ +\begin{code} +mkTyVarTy :: TyVar -> Type +mkTyVarTy = TyVarTy - [] -> voidTy -- Empty dictionary represented by Void +mkTyVarTys :: [TyVar] -> [Type] +mkTyVarTys = map mkTyVarTy -- a common use of mkTyVarTy - [arg_ty] -> expandTy arg_ty -- just the itself +getTyVar :: String -> Type -> TyVar +getTyVar msg (TyVarTy tv) = tv +getTyVar msg (SourceTy p) = getTyVar msg (sourceTypeRep p) +getTyVar msg (NoteTy _ t) = getTyVar msg t +getTyVar msg ty@(UsageTy _ _) = pprPanic "getTyVar: UTy:" (text msg $$ pprType ty) +getTyVar msg other = panic ("getTyVar: " ++ msg) + +getTyVar_maybe :: Type -> Maybe TyVar +getTyVar_maybe (TyVarTy tv) = Just tv +getTyVar_maybe (NoteTy _ t) = getTyVar_maybe t +getTyVar_maybe (SourceTy p) = getTyVar_maybe (sourceTypeRep p) +getTyVar_maybe ty@(UsageTy _ _) = pprPanic "getTyVar_maybe: UTy:" (pprType ty) +getTyVar_maybe other = Nothing + +isTyVarTy :: Type -> Bool +isTyVarTy (TyVarTy tv) = True +isTyVarTy (NoteTy _ ty) = isTyVarTy ty +isTyVarTy (SourceTy p) = isTyVarTy (sourceTypeRep p) +isTyVarTy ty@(UsageTy _ _) = pprPanic "isTyVarTy: UTy:" (pprType ty) +isTyVarTy other = False +\end{code} - -- The extra expandTy is to make sure that - -- the result isn't still a dict, which it might be - -- if the original guy was a dict with one superdict and - -- no methods! - other -> ASSERT(not (null all_arg_tys)) - foldl AppTy (TyConTy (tupleTyCon (length all_arg_tys)) u) all_arg_tys +--------------------------------------------------------------------- + AppTy + ~~~~~ +We need to be pretty careful with AppTy to make sure we obey the +invariant that a TyConApp is always visibly so. mkAppTy maintains the +invariant: use it. - -- A tuple of 'em - -- Note: length of all_arg_tys can be 0 if the class is - -- CCallable, CReturnable (and anything else - -- *really weird* that the user writes). +\begin{code} +mkAppTy orig_ty1 orig_ty2 + = ASSERT( not (isSourceTy orig_ty1) ) -- Source types are of kind * + UASSERT2( not (isUTy orig_ty2), pprType orig_ty1 <+> pprType orig_ty2 ) + -- argument must be unannotated + mk_app orig_ty1 + where + mk_app (NoteTy _ ty1) = mk_app ty1 + mk_app (TyConApp tc tys) = mkTyConApp tc (tys ++ [orig_ty2]) + mk_app ty@(UsageTy _ _) = pprPanic "mkAppTy: UTy:" (pprType ty) + mk_app ty1 = AppTy orig_ty1 orig_ty2 + +mkAppTys :: Type -> [Type] -> Type +mkAppTys orig_ty1 [] = orig_ty1 + -- This check for an empty list of type arguments + -- avoids the needless loss of a type synonym constructor. + -- For example: mkAppTys Rational [] + -- returns to (Ratio Integer), which has needlessly lost + -- the Rational part. +mkAppTys orig_ty1 orig_tys2 + = ASSERT( not (isSourceTy orig_ty1) ) -- Source types are of kind * + UASSERT2( not (any isUTy orig_tys2), pprType orig_ty1 <+> fsep (map pprType orig_tys2) ) + -- arguments must be unannotated + mk_app orig_ty1 + where + mk_app (NoteTy _ ty1) = mk_app ty1 + mk_app (TyConApp tc tys) = mkTyConApp tc (tys ++ orig_tys2) + mk_app ty@(UsageTy _ _) = pprPanic "mkAppTys: UTy:" (pprType ty) + mk_app ty1 = foldl AppTy orig_ty1 orig_tys2 + +splitAppTy_maybe :: Type -> Maybe (Type, Type) +splitAppTy_maybe (FunTy ty1 ty2) = Just (TyConApp funTyCon [unUTy ty1], unUTy ty2) +splitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2) +splitAppTy_maybe (NoteTy _ ty) = splitAppTy_maybe ty +splitAppTy_maybe (SourceTy p) = splitAppTy_maybe (sourceTypeRep p) +splitAppTy_maybe (TyConApp tc []) = Nothing +splitAppTy_maybe (TyConApp tc tys) = split tys [] + where + split [ty2] acc = Just (TyConApp tc (reverse acc), ty2) + split (ty:tys) acc = split tys (ty:acc) + +splitAppTy_maybe ty@(UsageTy _ _) = pprPanic "splitAppTy_maybe: UTy:" (pprType ty) +splitAppTy_maybe other = Nothing + +splitAppTy :: Type -> (Type, Type) +splitAppTy ty = case splitAppTy_maybe ty of + Just pr -> pr + Nothing -> panic "splitAppTy" + +splitAppTys :: Type -> (Type, [Type]) +splitAppTys ty = split ty ty [] where - (tyvar, super_classes, ops) = classSig clas - super_dict_tys = map mk_super_ty super_classes - class_op_tys = map mk_op_ty ops - all_arg_tys = super_dict_tys ++ class_op_tys - mk_super_ty sc = DictTy sc ty usageOmega - mk_op_ty op = instantiateTy [(tyvar,ty)] (classOpLocalType op) - -expandTy ty = ty + split orig_ty (AppTy ty arg) args = split ty ty (arg:args) + split orig_ty (NoteTy _ ty) args = split orig_ty ty args + split orig_ty (SourceTy p) args = split orig_ty (sourceTypeRep p) args + split orig_ty (FunTy ty1 ty2) args = ASSERT( null args ) + (TyConApp funTyCon [], [unUTy ty1,unUTy ty2]) + split orig_ty (TyConApp tc tc_args) args = (TyConApp tc [], tc_args ++ args) + split orig_ty (UsageTy _ _) args = pprPanic "splitAppTys: UTy:" (pprType orig_ty) + split orig_ty ty args = (orig_ty, args) \end{code} -Simple construction and analysis functions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -\begin{code} -mkTyVarTy :: t -> GenType t u -mkTyVarTys :: [t] -> [GenType t y] -mkTyVarTy = TyVarTy -mkTyVarTys = map mkTyVarTy -- a common use of mkTyVarTy - -getTyVar :: String -> GenType t u -> t -getTyVar msg (TyVarTy tv) = tv -getTyVar msg (SynTy _ _ t) = getTyVar msg t -getTyVar msg other = panic ("getTyVar: " ++ msg) -getTyVar_maybe :: GenType t u -> Maybe t -getTyVar_maybe (TyVarTy tv) = Just tv -getTyVar_maybe (SynTy _ _ t) = getTyVar_maybe t -getTyVar_maybe other = Nothing +--------------------------------------------------------------------- + FunTy + ~~~~~ -isTyVarTy :: GenType t u -> Bool -isTyVarTy (TyVarTy tv) = True -isTyVarTy (SynTy _ _ t) = isTyVarTy t -isTyVarTy other = False +\begin{code} +mkFunTy :: Type -> Type -> Type +mkFunTy arg res = UASSERT2( isUTy arg && isUTy res, pprType arg <+> pprType res ) + FunTy arg res + +mkFunTys :: [Type] -> Type -> Type +mkFunTys tys ty = UASSERT2( all isUTy (ty:tys), fsep (map pprType (tys++[ty])) ) + foldr FunTy ty tys + +splitFunTy :: Type -> (Type, Type) +splitFunTy (FunTy arg res) = (arg, res) +splitFunTy (NoteTy _ ty) = splitFunTy ty +splitFunTy (SourceTy p) = splitFunTy (sourceTypeRep p) +splitFunTy ty@(UsageTy _ _) = pprPanic "splitFunTy: UTy:" (pprType ty) + +splitFunTy_maybe :: Type -> Maybe (Type, Type) +splitFunTy_maybe (FunTy arg res) = Just (arg, res) +splitFunTy_maybe (NoteTy _ ty) = splitFunTy_maybe ty +splitFunTy_maybe (SourceTy p) = splitFunTy_maybe (sourceTypeRep p) +splitFunTy_maybe ty@(UsageTy _ _) = pprPanic "splitFunTy_maybe: UTy:" (pprType ty) +splitFunTy_maybe other = Nothing + +splitFunTys :: Type -> ([Type], Type) +splitFunTys ty = split [] ty ty + where + split args orig_ty (FunTy arg res) = split (arg:args) res res + split args orig_ty (NoteTy _ ty) = split args orig_ty ty + split args orig_ty (SourceTy p) = split args orig_ty (sourceTypeRep p) + split args orig_ty (UsageTy _ _) = pprPanic "splitFunTys: UTy:" (pprType orig_ty) + split args orig_ty ty = (reverse args, orig_ty) + +zipFunTys :: Outputable a => [a] -> Type -> ([(a,Type)], Type) +zipFunTys orig_xs orig_ty = split [] orig_xs orig_ty orig_ty + where + split acc [] nty ty = (reverse acc, nty) + split acc (x:xs) nty (FunTy arg res) = split ((x,arg):acc) xs res res + split acc xs nty (NoteTy _ ty) = split acc xs nty ty + split acc xs nty (SourceTy p) = split acc xs nty (sourceTypeRep p) + split acc xs nty (UsageTy _ _) = pprPanic "zipFunTys: UTy:" (ppr orig_xs <+> pprType orig_ty) + split acc (x:xs) nty ty = pprPanic "zipFunTys" (ppr orig_xs <+> pprType orig_ty) + +funResultTy :: Type -> Type +funResultTy (FunTy arg res) = res +funResultTy (NoteTy _ ty) = funResultTy ty +funResultTy (SourceTy p) = funResultTy (sourceTypeRep p) +funResultTy (UsageTy _ ty) = funResultTy ty +funResultTy ty = pprPanic "funResultTy" (pprType ty) + +funArgTy :: Type -> Type +funArgTy (FunTy arg res) = arg +funArgTy (NoteTy _ ty) = funArgTy ty +funArgTy (SourceTy p) = funArgTy (sourceTypeRep p) +funArgTy (UsageTy _ ty) = funArgTy ty +funArgTy ty = pprPanic "funArgTy" (pprType ty) \end{code} + +--------------------------------------------------------------------- + TyConApp + ~~~~~~~~ +@mkTyConApp@ is a key function, because it builds a TyConApp, FunTy or SourceTy, +as apppropriate. + \begin{code} -mkAppTy = AppTy +mkTyConApp :: TyCon -> [Type] -> Type +-- Assumes TyCon is not a SynTyCon; use mkSynTy instead for those +mkTyConApp tycon tys + | isFunTyCon tycon, [ty1,ty2] <- tys + = FunTy (mkUTyM ty1) (mkUTyM ty2) -mkAppTys :: GenType t u -> [GenType t u] -> GenType t u -mkAppTys t ts = foldl AppTy t ts + | isNewTyCon tycon, -- A saturated newtype application; + not (isRecursiveTyCon tycon), -- Not recursive (we don't use SourceTypes for them) + length tys == tyConArity tycon -- use the SourceType form + = SourceTy (NType tycon tys) -splitAppTy :: GenType t u -> (GenType t u, [GenType t u]) -splitAppTy t = go t [] - where - go (AppTy t arg) ts = go t (arg:ts) - go (FunTy fun arg u) ts = (TyConTy mkFunTyCon u, fun:arg:ts) - go (SynTy _ _ t) ts = go t ts - go t ts = (t,ts) + | otherwise + = ASSERT(not (isSynTyCon tycon)) + UASSERT2( not (any isUTy tys), ppr tycon <+> fsep (map pprType tys) ) + TyConApp tycon tys + +mkTyConTy :: TyCon -> Type +mkTyConTy tycon = ASSERT( not (isSynTyCon tycon) ) + TyConApp tycon [] + +-- splitTyConApp "looks through" synonyms, because they don't +-- mean a distinct type, but all other type-constructor applications +-- including functions are returned as Just .. + +tyConAppTyCon :: Type -> TyCon +tyConAppTyCon ty = fst (splitTyConApp ty) + +tyConAppArgs :: Type -> [Type] +tyConAppArgs ty = snd (splitTyConApp ty) + +splitTyConApp :: Type -> (TyCon, [Type]) +splitTyConApp ty = case splitTyConApp_maybe ty of + Just stuff -> stuff + Nothing -> pprPanic "splitTyConApp" (pprType ty) + +splitTyConApp_maybe :: Type -> Maybe (TyCon, [Type]) +splitTyConApp_maybe (TyConApp tc tys) = Just (tc, tys) +splitTyConApp_maybe (FunTy arg res) = Just (funTyCon, [unUTy arg,unUTy res]) +splitTyConApp_maybe (NoteTy _ ty) = splitTyConApp_maybe ty +splitTyConApp_maybe (SourceTy p) = splitTyConApp_maybe (sourceTypeRep p) +splitTyConApp_maybe (UsageTy _ ty) = splitTyConApp_maybe ty +splitTyConApp_maybe other = Nothing \end{code} + +--------------------------------------------------------------------- + SynTy + ~~~~~ + \begin{code} --- NB mkFunTy, mkFunTys puts in Omega usages, for now at least -mkFunTy arg res = FunTy arg res usageOmega - -mkFunTys :: [GenType t u] -> GenType t u -> GenType t u -mkFunTys ts t = foldr (\ f a -> FunTy f a usageOmega) t ts - - -- getFunTy_maybe and splitFunTy *must* have the general type given, which - -- means they *can't* do the DictTy jiggery-pokery that - -- *is* sometimes required. Hence we also have the ExpandingDicts variants - -- The relationship between these - -- two functions is like that between eqTy and eqSimpleTy. - -- ToDo: NUKE when we do dicts via newtype - -getFunTy_maybe :: GenType t u -> Maybe (GenType t u, GenType t u) -getFunTy_maybe (FunTy arg result _) = Just (arg,result) -getFunTy_maybe (AppTy (AppTy (TyConTy tycon _) arg) res) - | isFunTyCon tycon = Just (arg, res) -getFunTy_maybe (SynTy _ _ t) = getFunTy_maybe t -getFunTy_maybe other = Nothing - -getFunTyExpandingDicts_maybe :: Bool -- True <=> peek inside newtype applicatons - -> Type - -> Maybe (Type, Type) - -getFunTyExpandingDicts_maybe peek (FunTy arg result _) = Just (arg,result) -getFunTyExpandingDicts_maybe peek - (AppTy (AppTy (TyConTy tycon _) arg) res) | isFunTyCon tycon = Just (arg, res) -getFunTyExpandingDicts_maybe peek (SynTy _ _ t) = getFunTyExpandingDicts_maybe peek t -getFunTyExpandingDicts_maybe peek ty@(DictTy _ _ _) = getFunTyExpandingDicts_maybe peek (expandTy ty) - -getFunTyExpandingDicts_maybe True (ForAllTy _ ty) = getFunTyExpandingDicts_maybe True ty - -- Ignore for-alls when peeking. See note with defn of getFunTyExpandingDictsAndPeeking - -getFunTyExpandingDicts_maybe peek other - | not peek = Nothing -- that was easy - | otherwise - = case (maybeAppTyCon other) of - Nothing -> Nothing - Just (tc, arg_tys) - | not (isNewTyCon tc) -> Nothing - | otherwise -> - let - [newtype_con] = tyConDataCons tc -- there must be exactly one... - [inside_ty] = dataConArgTys newtype_con arg_tys - in - getFunTyExpandingDicts_maybe peek inside_ty - -splitFunTy :: GenType t u -> ([GenType t u], GenType t u) -splitFunTyExpandingDicts :: Type -> ([Type], Type) -splitFunTyExpandingDictsAndPeeking :: Type -> ([Type], Type) - -splitFunTy t = split_fun_ty getFunTy_maybe t -splitFunTyExpandingDicts t = split_fun_ty (getFunTyExpandingDicts_maybe False) t -splitFunTyExpandingDictsAndPeeking t = split_fun_ty (getFunTyExpandingDicts_maybe True) t - -- This "peeking" stuff is used only by the code generator. - -- It's interested in the representation type of things, ignoring: - -- newtype - -- foralls - -- expanding dictionary reps - -- synonyms, of course - -split_fun_ty get t = go t [] +mkSynTy tycon tys + | n_args == arity -- Exactly saturated + = mk_syn tys + | n_args > arity -- Over-saturated + = foldl AppTy (mk_syn (take arity tys)) (drop arity tys) + | otherwise -- Un-saturated + = TyConApp tycon tys + -- For the un-saturated case we build TyConApp directly + -- (mkTyConApp ASSERTs that the tc isn't a SynTyCon). + -- Here we are relying on checkValidType to find + -- the error. What we can't do is use mkSynTy with + -- too few arg tys, because that is utterly bogus. + where - go t ts = case (get t) of - Just (arg,res) -> go res (arg:ts) - Nothing -> (reverse ts, t) + mk_syn tys = NoteTy (SynNote (TyConApp tycon tys)) + (substTyWith tyvars tys body) + + (tyvars, body) = ASSERT( isSynTyCon tycon ) getSynTyConDefn tycon + arity = tyConArity tycon + n_args = length tys \end{code} -\begin{code} --- NB applyTyCon puts in usageOmega, for now at least -mkTyConTy tycon - = ASSERT(not (isSynTyCon tycon)) - TyConTy tycon usageOmega +Notes on type synonyms +~~~~~~~~~~~~~~~~~~~~~~ +The various "split" functions (splitFunTy, splitRhoTy, splitForAllTy) try +to return type synonyms whereever possible. Thus -applyTyCon :: TyCon -> [GenType t u] -> GenType t u -applyTyCon tycon tys - = ASSERT (not (isSynTyCon tycon)) - --(if (not (isSynTyCon tycon)) then \x->x else pprTrace "applyTyCon:" (pprTyCon PprDebug tycon)) $ - foldl AppTy (TyConTy tycon usageOmega) tys + type Foo a = a -> a -getTyCon_maybe :: GenType t u -> Maybe TyCon ---getTyConExpandingDicts_maybe :: Type -> Maybe TyCon +we want + splitFunTys (a -> Foo a) = ([a], Foo a) +not ([a], a -> a) -getTyCon_maybe (TyConTy tycon _) = Just tycon -getTyCon_maybe (SynTy _ _ t) = getTyCon_maybe t -getTyCon_maybe other_ty = Nothing +The reason is that we then get better (shorter) type signatures in +interfaces. Notably this plays a role in tcTySigs in TcBinds.lhs. ---getTyConExpandingDicts_maybe (TyConTy tycon _) = Just tycon ---getTyConExpandingDicts_maybe (SynTy _ _ t) = getTyConExpandingDicts_maybe t ---getTyConExpandingDicts_maybe ty@(DictTy _ _ _) = getTyConExpandingDicts_maybe (expandTy ty) ---getTyConExpandingDicts_maybe other_ty = Nothing -\end{code} + + Representation types + ~~~~~~~~~~~~~~~~~~~~ + +repType looks through + (a) for-alls, and + (b) synonyms + (c) predicates + (d) usage annotations + (e) [recursive] newtypes +It's useful in the back end. + +Remember, non-recursive newtypes get expanded as part of the SourceTy case, +but recursive ones are represented by TyConApps and have to be expanded +by steam. \begin{code} -mkSynTy syn_tycon tys - = ASSERT(isSynTyCon syn_tycon) - SynTy syn_tycon tys (instantiateTauTy (zipEqual "mkSynTy" tyvars tys) body) +repType :: Type -> Type +repType (ForAllTy _ ty) = repType ty +repType (NoteTy _ ty) = repType ty +repType (SourceTy p) = repType (sourceTypeRep p) +repType (UsageTy _ ty) = repType ty +repType (TyConApp tc tys) | isNewTyCon tc && length tys == tyConArity tc + = repType (newTypeRep tc tys) +repType ty = ty + +splitRepFunTys :: Type -> ([Type], Type) +-- Like splitFunTys, but looks through newtypes and for-alls +splitRepFunTys ty = split [] (repType ty) where - (tyvars, body) = getSynTyConDefn syn_tycon -\end{code} + split args (FunTy arg res) = split (arg:args) (repType res) + split args ty = (reverse args, ty) -Tau stuff -~~~~~~~~~ -\begin{code} -isTauTy :: GenType t u -> Bool -isTauTy (TyVarTy v) = True -isTauTy (TyConTy _ _) = True -isTauTy (AppTy a b) = isTauTy a && isTauTy b -isTauTy (FunTy a b _) = isTauTy a && isTauTy b -isTauTy (SynTy _ _ ty) = isTauTy ty -isTauTy other = False +typePrimRep :: Type -> PrimRep +typePrimRep ty = case repType ty of + TyConApp tc _ -> tyConPrimRep tc + FunTy _ _ -> PtrRep + AppTy _ _ -> PtrRep -- ?? + TyVarTy _ -> PtrRep \end{code} -Rho stuff -~~~~~~~~~ -NB mkRhoTy and mkDictTy put in usageOmega, for now at least -\begin{code} -mkDictTy :: Class -> GenType t u -> GenType t u -mkDictTy clas ty = DictTy clas ty usageOmega -mkRhoTy :: [(Class, GenType t u)] -> GenType t u -> GenType t u -mkRhoTy theta ty = - foldr (\(c,t) r -> FunTy (DictTy c t usageOmega) r usageOmega) ty theta +--------------------------------------------------------------------- + ForAllTy + ~~~~~~~~ -splitRhoTy :: GenType t u -> ([(Class,GenType t u)], GenType t u) -splitRhoTy t = - go t [] - where - go (FunTy (DictTy c t _) r _) ts = go r ((c,t):ts) - go (AppTy (AppTy (TyConTy tycon _) (DictTy c t _)) r) ts - | isFunTyCon tycon - = go r ((c,t):ts) - go (SynTy _ _ t) ts = go t ts - go t ts = (reverse ts, t) - - -mkTheta :: [Type] -> ThetaType - -- recover a ThetaType from the types of some dictionaries -mkTheta dict_tys - = map cvt dict_tys +\begin{code} +mkForAllTy :: TyVar -> Type -> Type +mkForAllTy tyvar ty + = mkForAllTys [tyvar] ty + +mkForAllTys :: [TyVar] -> Type -> Type +mkForAllTys tyvars ty + = case splitUTy_maybe ty of + Just (u,ty1) -> UASSERT2( not (mkVarSet tyvars `intersectsVarSet` tyVarsOfType u), + ptext SLIT("mkForAllTys: usage scope") + <+> ppr tyvars <+> pprType ty ) + mkUTy u (foldr ForAllTy ty1 tyvars) -- we lift usage annotations over foralls + Nothing -> foldr ForAllTy ty tyvars + +isForAllTy :: Type -> Bool +isForAllTy (NoteTy _ ty) = isForAllTy ty +isForAllTy (ForAllTy _ _) = True +isForAllTy (UsageTy _ ty) = isForAllTy ty +isForAllTy other_ty = False + +splitForAllTy_maybe :: Type -> Maybe (TyVar, Type) +splitForAllTy_maybe ty = splitFAT_m ty where - cvt (DictTy clas ty _) = (clas, ty) - cvt other = panic "Type.mkTheta" -- pprPanic "mkTheta:" (pprType PprDebug other) - -isDictTy (DictTy _ _ _) = True -isDictTy (SynTy _ _ t) = isDictTy t -isDictTy _ = False + splitFAT_m (NoteTy _ ty) = splitFAT_m ty + splitFAT_m (SourceTy p) = splitFAT_m (sourceTypeRep p) + splitFAT_m (ForAllTy tyvar ty) = Just(tyvar, ty) + splitFAT_m (UsageTy _ ty) = splitFAT_m ty + splitFAT_m _ = Nothing + +splitForAllTys :: Type -> ([TyVar], Type) +splitForAllTys ty = split ty ty [] + where + split orig_ty (ForAllTy tv ty) tvs = split ty ty (tv:tvs) + split orig_ty (NoteTy _ ty) tvs = split orig_ty ty tvs + split orig_ty (SourceTy p) tvs = split orig_ty (sourceTypeRep p) tvs + split orig_ty (UsageTy _ ty) tvs = split orig_ty ty tvs + split orig_ty t tvs = (reverse tvs, orig_ty) \end{code} +-- (mkPiType now in CoreUtils) + +Applying a for-all to its arguments. Lift usage annotation as required. -Forall stuff -~~~~~~~~~~~~ \begin{code} -mkForAllTy = ForAllTy - -mkForAllTys :: [t] -> GenType t u -> GenType t u -mkForAllTys tyvars ty = foldr ForAllTy ty tyvars - -getForAllTy_maybe :: GenType t u -> Maybe (t,GenType t u) -getForAllTy_maybe (SynTy _ _ t) = getForAllTy_maybe t -getForAllTy_maybe (ForAllTy tyvar t) = Just(tyvar,t) -getForAllTy_maybe _ = Nothing - -getForAllTyExpandingDicts_maybe :: Type -> Maybe (TyVar, Type) -getForAllTyExpandingDicts_maybe (SynTy _ _ t) = getForAllTyExpandingDicts_maybe t -getForAllTyExpandingDicts_maybe (ForAllTy tyvar t) = Just(tyvar,t) -getForAllTyExpandingDicts_maybe ty@(DictTy _ _ _) = getForAllTyExpandingDicts_maybe (expandTy ty) -getForAllTyExpandingDicts_maybe _ = Nothing - -splitForAllTy :: GenType t u-> ([t], GenType t u) -splitForAllTy t = go t [] - where - go (ForAllTy tv t) tvs = go t (tv:tvs) - go (SynTy _ _ t) tvs = go t tvs - go t tvs = (reverse tvs, t) +applyTy :: Type -> Type -> Type +applyTy (SourceTy p) arg = applyTy (sourceTypeRep p) arg +applyTy (NoteTy _ fun) arg = applyTy fun arg +applyTy (ForAllTy tv ty) arg = UASSERT2( not (isUTy arg), + ptext SLIT("applyTy") + <+> pprType ty <+> pprType arg ) + substTyWith [tv] [arg] ty +applyTy (UsageTy u ty) arg = UsageTy u (applyTy ty arg) +applyTy other arg = panic "applyTy" + +applyTys :: Type -> [Type] -> Type +applyTys fun_ty arg_tys + = UASSERT2( not (any isUTy arg_tys), ptext SLIT("applyTys") <+> pprType fun_ty ) + (case mu of + Just u -> UsageTy u + Nothing -> id) $ + substTyWith tvs arg_tys ty + where + (mu, tvs, ty) = split fun_ty arg_tys + + split fun_ty [] = (Nothing, [], fun_ty) + split (NoteTy _ fun_ty) args = split fun_ty args + split (SourceTy p) args = split (sourceTypeRep p) args + split (ForAllTy tv fun_ty) (arg:args) = case split fun_ty args of + (mu, tvs, ty) -> (mu, tv:tvs, ty) + split (UsageTy u ty) args = case split ty args of + (Nothing, tvs, ty) -> (Just u, tvs, ty) + (Just _ , _ , _ ) -> pprPanic "applyTys:" + (pprType fun_ty) + split other_ty args = panic "applyTys" \end{code} -\begin{code} -mkForAllUsageTy :: u -> [u] -> GenType t u -> GenType t u -mkForAllUsageTy = ForAllUsageTy -getForAllUsageTy :: GenType t u -> Maybe (u,[u],GenType t u) -getForAllUsageTy (ForAllUsageTy uvar bounds t) = Just(uvar,bounds,t) -getForAllUsageTy (SynTy _ _ t) = getForAllUsageTy t -getForAllUsageTy _ = Nothing -\end{code} +--------------------------------------------------------------------- + UsageTy + ~~~~~~~ + +Constructing and taking apart usage types. -Applied tycons (includes FunTyCons) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} -maybeAppTyCon - :: GenType tyvar uvar - -> Maybe (TyCon, -- the type constructor - [GenType tyvar uvar]) -- types to which it is applied - -maybeAppTyCon ty - = case (getTyCon_maybe app_ty) of - Nothing -> Nothing - Just tycon -> Just (tycon, arg_tys) - where - (app_ty, arg_tys) = splitAppTy ty +mkUTy :: Type -> Type -> Type +mkUTy u ty + = ASSERT2( typeKind u `eqKind` usageTypeKind, + ptext SLIT("mkUTy:") <+> pprType u <+> pprType ty ) + UASSERT2( not (isUTy ty), ptext SLIT("mkUTy:") <+> pprType u <+> pprType ty ) + -- if u == usMany then ty else : ToDo? KSW 2000-10 +#ifdef DO_USAGES + UsageTy u ty +#else + ty +#endif + +splitUTy :: Type -> (Type {- :: $ -}, Type) +splitUTy orig_ty + = case splitUTy_maybe orig_ty of + Just (u,ty) -> (u,ty) +#ifdef DO_USAGES + Nothing -> pprPanic "splitUTy:" (pprType orig_ty) +#else + Nothing -> (usMany,orig_ty) -- default annotation ToDo KSW 2000-10 +#endif +splitUTy_maybe :: Type -> Maybe (Type {- :: $ -}, Type) +splitUTy_maybe (UsageTy u ty) = Just (u,ty) +splitUTy_maybe (NoteTy _ ty) = splitUTy_maybe ty +splitUTy_maybe other_ty = Nothing -getAppTyCon - :: GenType tyvar uvar - -> (TyCon, -- the type constructor - [GenType tyvar uvar]) -- types to which it is applied +isUTy :: Type -> Bool + -- has usage annotation +isUTy = maybeToBool . splitUTy_maybe -getAppTyCon ty - = case maybeAppTyCon ty of - Just stuff -> stuff -#ifdef DEBUG - Nothing -> panic "Type.getAppTyCon" -- (ppr PprShowAll ty) -#endif +uaUTy :: Type -> Type + -- extract annotation +uaUTy = fst . splitUTy + +unUTy :: Type -> Type + -- extract unannotated type +unUTy = snd . splitUTy \end{code} -Applied data tycons (give back constrs) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} -maybeAppDataTyCon - :: GenType (GenTyVar any) uvar - -> Maybe (TyCon, -- the type constructor - [GenType (GenTyVar any) uvar], -- types to which it is applied - [Id]) -- its family of data-constructors -maybeAppDataTyConExpandingDicts, maybeAppSpecDataTyConExpandingDicts - :: Type -> Maybe (TyCon, [Type], [Id]) +liftUTy :: (Type -> Type) -> Type -> Type + -- lift outer usage annot over operation on unannotated types +liftUTy f ty + = let + (u,ty') = splitUTy ty + in + mkUTy u (f ty') +\end{code} -maybeAppDataTyCon ty = maybe_app_data_tycon (\x->x) ty -maybeAppDataTyConExpandingDicts ty = maybe_app_data_tycon expandTy ty -maybeAppSpecDataTyConExpandingDicts ty = maybe_app_data_tycon expandTy ty +\begin{code} +mkUTyM :: Type -> Type + -- put TOP (no info) annotation on unannotated type +mkUTyM ty = mkUTy usMany ty +\end{code} +\begin{code} +isUsageKind :: Kind -> Bool +isUsageKind k + = ASSERT( typeKind k `eqKind` superKind ) + k `eqKind` usageTypeKind + +isUsage :: Type -> Bool +isUsage ty + = isUsageKind (typeKind ty) + +isUTyVar :: Var -> Bool +isUTyVar v + = isUsageKind (tyVarKind v) +\end{code} -maybe_app_data_tycon expand ty - = let - expanded_ty = expand ty - (app_ty, arg_tys) = splitAppTy expanded_ty - in - case (getTyCon_maybe app_ty) of - Just tycon | --pprTrace "maybe_app:" (ppCat [ppr PprDebug (isDataTyCon tycon), ppr PprDebug (notArrowKind (typeKind expanded_ty))]) $ - isDataTyCon tycon && - notArrowKind (typeKind expanded_ty) - -- Must be saturated for ty to be a data type - -> Just (tycon, arg_tys, tyConDataCons tycon) - - other -> Nothing - -getAppDataTyCon, getAppSpecDataTyCon - :: GenType (GenTyVar any) uvar - -> (TyCon, -- the type constructor - [GenType (GenTyVar any) uvar], -- types to which it is applied - [Id]) -- its family of data-constructors -getAppDataTyConExpandingDicts, getAppSpecDataTyConExpandingDicts - :: Type -> (TyCon, [Type], [Id]) - -getAppDataTyCon ty = get_app_data_tycon maybeAppDataTyCon ty -getAppDataTyConExpandingDicts ty = --pprTrace "getAppDataTyConEx...:" (pprType PprDebug ty) $ - get_app_data_tycon maybeAppDataTyConExpandingDicts ty - --- these should work like the UniTyFuns.getUniDataSpecTyCon* things of old (ToDo) -getAppSpecDataTyCon = getAppDataTyCon -getAppSpecDataTyConExpandingDicts = getAppDataTyConExpandingDicts - -get_app_data_tycon maybe ty - = case maybe ty of - Just stuff -> stuff -#ifdef DEBUG - Nothing -> panic "Type.getAppDataTyCon"-- (pprGenType PprShowAll ty) -#endif +%************************************************************************ +%* * +\subsection{Source types} +%* * +%************************************************************************ -maybeBoxedPrimType :: Type -> Maybe (Id, Type) +A "source type" is a type that is a separate type as far as the type checker is +concerned, but which has low-level representation as far as the back end is concerned. -maybeBoxedPrimType ty - = case (maybeAppDataTyCon ty) of -- Data type, - Just (tycon, tys_applied, [data_con]) -- with exactly one constructor - -> case (dataConArgTys data_con tys_applied) of - [data_con_arg_ty] -- Applied to exactly one type, - | isPrimType data_con_arg_ty -- which is primitive - -> Just (data_con, data_con_arg_ty) - other_cases -> Nothing - other_cases -> Nothing -\end{code} +Source types are always lifted. -\begin{code} -splitSigmaTy :: GenType t u -> ([t], [(Class,GenType t u)], GenType t u) -splitSigmaTy ty = - (tyvars, theta, tau) - where - (tyvars,rho) = splitForAllTy ty - (theta,tau) = splitRhoTy rho +The key function is sourceTypeRep which gives the representation of a source type: -mkSigmaTy tyvars theta tau = mkForAllTys tyvars (mkRhoTy theta tau) +\begin{code} +mkPredTy :: PredType -> Type +mkPredTy pred = SourceTy pred + +mkPredTys :: ThetaType -> [Type] +mkPredTys preds = map SourceTy preds + +sourceTypeRep :: SourceType -> Type +-- Convert a predicate to its "representation type"; +-- the type of evidence for that predicate, which is actually passed at runtime +sourceTypeRep (IParam n ty) = ty +sourceTypeRep (ClassP clas tys) = mkTyConApp (classTyCon clas) tys + -- Note the mkTyConApp; the classTyCon might be a newtype! +sourceTypeRep (NType tc tys) = newTypeRep tc tys + -- ToDo: Consider caching this substitution in a NType + +isSourceTy :: Type -> Bool +isSourceTy (NoteTy _ ty) = isSourceTy ty +isSourceTy (UsageTy _ ty) = isSourceTy ty +isSourceTy (SourceTy sty) = True +isSourceTy _ = False + + +splitNewType_maybe :: Type -> Maybe Type +-- Newtypes that are recursive are reprsented by TyConApp, just +-- as they always were. Occasionally we want to find their representation type. +-- NB: remember that in this module, non-recursive newtypes are transparent + +splitNewType_maybe ty + = case splitTyConApp_maybe ty of + Just (tc,tys) | isNewTyCon tc -> ASSERT( length tys == tyConArity tc ) + -- The assert should hold because repType should + -- only be applied to *types* (of kind *) + Just (newTypeRep tc tys) + other -> Nothing + +-- A local helper function (not exported) +newTypeRep new_tycon tys = case newTyConRep new_tycon of + (tvs, rep_ty) -> substTyWith tvs tys rep_ty \end{code} -Finding the kind of a type -~~~~~~~~~~~~~~~~~~~~~~~~~~ +%************************************************************************ +%* * +\subsection{Kinds and free variables} +%* * +%************************************************************************ + +--------------------------------------------------------------------- + Finding the kind of a type + ~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} -typeKind :: GenType (GenTyVar any) u -> Kind - -typeKind (TyVarTy tyvar) = tyVarKind tyvar -typeKind (TyConTy tycon usage) = tyConKind tycon -typeKind (SynTy _ _ ty) = typeKind ty -typeKind (FunTy fun arg _) = mkBoxedTypeKind -typeKind (DictTy clas arg _) = mkBoxedTypeKind -typeKind (AppTy fun arg) = resultKind (typeKind fun) -typeKind (ForAllTy _ _) = mkBoxedTypeKind -typeKind (ForAllUsageTy _ _ _) = mkBoxedTypeKind +typeKind :: Type -> Kind + +typeKind (TyVarTy tyvar) = tyVarKind tyvar +typeKind (TyConApp tycon tys) = foldr (\_ k -> funResultTy k) (tyConKind tycon) tys +typeKind (NoteTy _ ty) = typeKind ty +typeKind (SourceTy _) = liftedTypeKind -- Predicates are always + -- represented by lifted types +typeKind (AppTy fun arg) = funResultTy (typeKind fun) + +typeKind (FunTy arg res) = fix_up (typeKind res) + where + fix_up (TyConApp tycon _) | tycon == typeCon + || tycon == openKindCon = liftedTypeKind + fix_up (NoteTy _ kind) = fix_up kind + fix_up kind = kind + -- The basic story is + -- typeKind (FunTy arg res) = typeKind res + -- But a function is lifted regardless of its result type + -- Hence the strange fix-up. + -- Note that 'res', being the result of a FunTy, can't have + -- a strange kind like (*->*). + +typeKind (ForAllTy tv ty) = typeKind ty +typeKind (UsageTy _ ty) = typeKind ty -- we don't have separate kinds for ann/unann \end{code} -Free variables of a type -~~~~~~~~~~~~~~~~~~~~~~~~ +--------------------------------------------------------------------- + Free variables of a type + ~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} -tyVarsOfType :: GenType (GenTyVar flexi) uvar -> GenTyVarSet flexi - -tyVarsOfType (TyVarTy tv) = unitTyVarSet tv -tyVarsOfType (TyConTy tycon usage) = emptyTyVarSet -tyVarsOfType (SynTy _ tys ty) = tyVarsOfTypes tys -tyVarsOfType (FunTy arg res _) = tyVarsOfType arg `unionTyVarSets` tyVarsOfType res -tyVarsOfType (AppTy fun arg) = tyVarsOfType fun `unionTyVarSets` tyVarsOfType arg -tyVarsOfType (DictTy clas ty _) = tyVarsOfType ty -tyVarsOfType (ForAllTy tyvar ty) = tyVarsOfType ty `minusTyVarSet` unitTyVarSet tyvar -tyVarsOfType (ForAllUsageTy _ _ ty) = tyVarsOfType ty - -tyVarsOfTypes :: [GenType (GenTyVar flexi) uvar] -> GenTyVarSet flexi -tyVarsOfTypes tys = foldr (unionTyVarSets.tyVarsOfType) emptyTyVarSet tys - --- Find the free names of a type, including the type constructors and classes it mentions -namesOfType :: GenType (GenTyVar flexi) uvar -> NameSet -namesOfType (TyVarTy tv) = unitNameSet (getName tv) -namesOfType (TyConTy tycon usage) = unitNameSet (getName tycon) -namesOfType (SynTy tycon tys ty) = unitNameSet (getName tycon) `unionNameSets` - namesOfType ty -namesOfType (FunTy arg res _) = namesOfType arg `unionNameSets` namesOfType res -namesOfType (AppTy fun arg) = namesOfType fun `unionNameSets` namesOfType arg -namesOfType (DictTy clas ty _) = unitNameSet (getName clas) `unionNameSets` - namesOfType ty -namesOfType (ForAllTy tyvar ty) = namesOfType ty `minusNameSet` unitNameSet (getName tyvar) -namesOfType (ForAllUsageTy _ _ ty) = panic "forall usage" +tyVarsOfType :: Type -> TyVarSet +tyVarsOfType (TyVarTy tv) = unitVarSet tv +tyVarsOfType (TyConApp tycon tys) = tyVarsOfTypes tys +tyVarsOfType (NoteTy (FTVNote tvs) ty2) = tvs +tyVarsOfType (NoteTy (SynNote ty1) ty2) = tyVarsOfType ty1 +tyVarsOfType (SourceTy sty) = tyVarsOfSourceType sty +tyVarsOfType (FunTy arg res) = tyVarsOfType arg `unionVarSet` tyVarsOfType res +tyVarsOfType (AppTy fun arg) = tyVarsOfType fun `unionVarSet` tyVarsOfType arg +tyVarsOfType (ForAllTy tyvar ty) = tyVarsOfType ty `minusVarSet` unitVarSet tyvar +tyVarsOfType (UsageTy u ty) = tyVarsOfType u `unionVarSet` tyVarsOfType ty + +tyVarsOfTypes :: [Type] -> TyVarSet +tyVarsOfTypes tys = foldr (unionVarSet.tyVarsOfType) emptyVarSet tys + +tyVarsOfPred :: PredType -> TyVarSet +tyVarsOfPred = tyVarsOfSourceType -- Just a subtype + +tyVarsOfSourceType :: SourceType -> TyVarSet +tyVarsOfSourceType (IParam n ty) = tyVarsOfType ty +tyVarsOfSourceType (ClassP clas tys) = tyVarsOfTypes tys +tyVarsOfSourceType (NType tc tys) = tyVarsOfTypes tys + +tyVarsOfTheta :: ThetaType -> TyVarSet +tyVarsOfTheta = foldr (unionVarSet . tyVarsOfSourceType) emptyVarSet + +-- Add a Note with the free tyvars to the top of the type +addFreeTyVars :: Type -> Type +addFreeTyVars ty@(NoteTy (FTVNote _) _) = ty +addFreeTyVars ty = NoteTy (FTVNote (tyVarsOfType ty)) ty \end{code} +Usage annotations of a type +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Get a list of usage annotations of a type, *in left-to-right pre-order*. -Instantiating a type -~~~~~~~~~~~~~~~~~~~~ \begin{code} --- applyTy :: GenType (GenTyVar flexi) uvar --- -> GenType (GenTyVar flexi) uvar --- -> GenType (GenTyVar flexi) uvar +usageAnnOfType :: Type -> [Type] +usageAnnOfType ty + = goS ty + where + goT (TyVarTy _) = [] + goT (AppTy ty1 ty2) = goT ty1 ++ goT ty2 + goT (TyConApp tc tys) = concatMap goT tys + goT (FunTy sty1 sty2) = goS sty1 ++ goS sty2 + goT (ForAllTy mv ty) = goT ty + goT (SourceTy p) = goT (sourceTypeRep p) + goT ty@(UsageTy _ _) = pprPanic "usageAnnOfType: unexpected usage:" (pprType ty) + goT (NoteTy note ty) = goT ty + + goS sty = case splitUTy sty of + (u,tty) -> u : goT tty +\end{code} -applyTy :: Type -> Type -> Type -applyTy (SynTy _ _ fun) arg = applyTy fun arg -applyTy (ForAllTy tv ty) arg = instantiateTy [(tv,arg)] ty -applyTy ty@(DictTy _ _ _) arg = applyTy (expandTy ty) arg -applyTy other arg = panic "applyTy" -\end{code} +%************************************************************************ +%* * +\subsection{TidyType} +%* * +%************************************************************************ + +tidyTy tidies up a type for printing in an error message, or in +an interface file. + +It doesn't change the uniques at all, just the print names. \begin{code} -instantiateTy :: [(GenTyVar flexi, GenType (GenTyVar flexi) uvar)] - -> GenType (GenTyVar flexi) uvar - -> GenType (GenTyVar flexi) uvar +tidyTyVarBndr :: TidyEnv -> TyVar -> (TidyEnv, TyVar) +tidyTyVarBndr (tidy_env, subst) tyvar + = case tidyOccName tidy_env (getOccName name) of + (tidy', occ') -> -- New occname reqd + ((tidy', subst'), tyvar') + where + subst' = extendVarEnv subst tyvar tyvar' + tyvar' = setTyVarName tyvar name' + name' = mkLocalName (getUnique name) occ' noSrcLoc + -- Note: make a *user* tyvar, so it printes nicely + -- Could extract src loc, but no need. + where + name = tyVarName tyvar -instantiateTauTy :: Eq tv => - [(tv, GenType tv' u)] - -> GenType tv u - -> GenType tv' u +tidyFreeTyVars :: TidyEnv -> TyVarSet -> TidyEnv +-- Add the free tyvars to the env in tidy form, +-- so that we can tidy the type they are free in +tidyFreeTyVars env tyvars = fst (tidyOpenTyVars env (varSetElems tyvars)) -applyTypeEnvToTy :: TyVarEnv Type -> SigmaType -> SigmaType +tidyOpenTyVars :: TidyEnv -> [TyVar] -> (TidyEnv, [TyVar]) +tidyOpenTyVars env tyvars = mapAccumL tidyOpenTyVar env tyvars --- instantiateTauTy works only (a) on types with no ForAlls, --- and when (b) all the type variables are being instantiated --- In return it is more polymorphic than instantiateTy +tidyOpenTyVar :: TidyEnv -> TyVar -> (TidyEnv, TyVar) +-- Treat a new tyvar as a binder, and give it a fresh tidy name +tidyOpenTyVar env@(tidy_env, subst) tyvar + = case lookupVarEnv subst tyvar of + Just tyvar' -> (env, tyvar') -- Already substituted + Nothing -> tidyTyVarBndr env tyvar -- Treat it as a binder -instant_help ty lookup_tv deflt_tv choose_tycon - if_usage if_forall bound_forall_tv_BAD deflt_forall_tv +tidyType :: TidyEnv -> Type -> Type +tidyType env@(tidy_env, subst) ty = go ty where - go (TyVarTy tv) = case (lookup_tv tv) of - Nothing -> deflt_tv tv - Just ty -> ty - go ty@(TyConTy tycon usage) = choose_tycon ty tycon usage - go (SynTy tycon tys ty) = SynTy tycon (map go tys) (go ty) - go (FunTy arg res usage) = FunTy (go arg) (go res) usage - go (AppTy fun arg) = AppTy (go fun) (go arg) - go (DictTy clas ty usage) = DictTy clas (go ty) usage - go (ForAllUsageTy uvar bds ty) = if_usage $ - ForAllUsageTy uvar bds (go ty) - go (ForAllTy tv ty) = if_forall $ - (if (bound_forall_tv_BAD && maybeToBool (lookup_tv tv)) then - trace "instantiateTy: unexpected forall hit" - else - \x->x) ForAllTy (deflt_forall_tv tv) (go ty) - -instantiateTy tenv ty - = instant_help ty lookup_tv deflt_tv choose_tycon - if_usage if_forall bound_forall_tv_BAD deflt_forall_tv - where - lookup_tv tv = case [ty | (tv',ty) <- tenv, tv == tv'] of - [] -> Nothing - [ty] -> Just ty - _ -> panic "instantiateTy:lookup_tv" - - deflt_tv tv = TyVarTy tv - choose_tycon ty _ _ = ty - if_usage ty = ty - if_forall ty = ty - bound_forall_tv_BAD = True - deflt_forall_tv tv = tv - -instantiateTauTy tenv ty - = instant_help ty lookup_tv deflt_tv choose_tycon - if_usage if_forall bound_forall_tv_BAD deflt_forall_tv - where - lookup_tv tv = case [ty | (tv',ty) <- tenv, tv == tv'] of - [] -> Nothing - [ty] -> Just ty - _ -> panic "instantiateTauTy:lookup_tv" - - deflt_tv tv = panic "instantiateTauTy" - choose_tycon _ tycon usage = TyConTy tycon usage - if_usage ty = panic "instantiateTauTy:ForAllUsageTy" - if_forall ty = panic "instantiateTauTy:ForAllTy" - bound_forall_tv_BAD = panic "instantiateTauTy:bound_forall_tv" - deflt_forall_tv tv = panic "instantiateTauTy:deflt_forall_tv" - - --- applyTypeEnv applies a type environment to a type. --- It can handle shadowing; for example: --- f = /\ t1 t2 -> \ d -> --- letrec f' = /\ t1 -> \x -> ...(f' t1 x')... --- in f' t1 --- Here, when we clone t1 to t1', say, we'll come across shadowing --- when applying the clone environment to the type of f'. --- --- As a sanity check, we should also check that name capture --- doesn't occur, but that means keeping track of the free variables of the --- range of the TyVarEnv, which I don't do just yet. --- --- We don't use instant_help because we need to carry in the environment - -applyTypeEnvToTy tenv ty - = go tenv ty - where - go tenv ty@(TyVarTy tv) = case (lookupTyVarEnv tenv tv) of - Nothing -> ty - Just ty -> ty - go tenv ty@(TyConTy tycon usage) = ty - go tenv (SynTy tycon tys ty) = SynTy tycon (map (go tenv) tys) (go tenv ty) - go tenv (FunTy arg res usage) = FunTy (go tenv arg) (go tenv res) usage - go tenv (AppTy fun arg) = AppTy (go tenv fun) (go tenv arg) - go tenv (DictTy clas ty usage) = DictTy clas (go tenv ty) usage - go tenv (ForAllUsageTy uvar bds ty) = ForAllUsageTy uvar bds (go tenv ty) - go tenv (ForAllTy tv ty) = ForAllTy tv (go tenv' ty) - where - tenv' = case lookupTyVarEnv tenv tv of - Nothing -> tenv - Just _ -> delFromTyVarEnv tenv tv + go (TyVarTy tv) = case lookupVarEnv subst tv of + Nothing -> TyVarTy tv + Just tv' -> TyVarTy tv' + go (TyConApp tycon tys) = let args = map go tys + in args `seqList` TyConApp tycon args + go (NoteTy note ty) = (NoteTy $! (go_note note)) $! (go ty) + go (SourceTy sty) = SourceTy (tidySourceType env sty) + go (AppTy fun arg) = (AppTy $! (go fun)) $! (go arg) + go (FunTy fun arg) = (FunTy $! (go fun)) $! (go arg) + go (ForAllTy tv ty) = ForAllTy tvp $! (tidyType envp ty) + where + (envp, tvp) = tidyTyVarBndr env tv + go (UsageTy u ty) = (UsageTy $! (go u)) $! (go ty) + + go_note (SynNote ty) = SynNote $! (go ty) + go_note note@(FTVNote ftvs) = note -- No need to tidy the free tyvars + +tidyTypes env tys = map (tidyType env) tys + +tidyPred :: TidyEnv -> SourceType -> SourceType +tidyPred = tidySourceType + +tidySourceType :: TidyEnv -> SourceType -> SourceType +tidySourceType env (IParam n ty) = IParam n (tidyType env ty) +tidySourceType env (ClassP clas tys) = ClassP clas (tidyTypes env tys) +tidySourceType env (NType tc tys) = NType tc (tidyTypes env tys) \end{code} -\begin{code} -instantiateUsage - :: Ord3 u => [(u, GenType t u')] -> GenType t u -> GenType t u' -instantiateUsage = panic "instantiateUsage: not implemented" -\end{code} - - -At present there are no unboxed non-primitive types, so -isUnboxedType is the same as isPrimType. - -We're a bit cavalier about finding out whether something is -primitive/unboxed or not. Rather than deal with the type -arguemnts we just zoom into the function part of the type. -That is, given (T a) we just recurse into the "T" part, -ignoring "a". +@tidyOpenType@ grabs the free type variables, tidies them +and then uses @tidyType@ to work over the type itself \begin{code} -isPrimType, isUnboxedType :: Type -> Bool - -isPrimType (AppTy ty _) = isPrimType ty -isPrimType (SynTy _ _ ty) = isPrimType ty -isPrimType (TyConTy tycon _) = case maybeNewTyCon tycon of - Just (tyvars, ty) -> isPrimType ty - Nothing -> isPrimTyCon tycon +tidyOpenType :: TidyEnv -> Type -> (TidyEnv, Type) +tidyOpenType env ty + = (env', tidyType env' ty) + where + env' = tidyFreeTyVars env (tyVarsOfType ty) -isPrimType _ = False +tidyOpenTypes :: TidyEnv -> [Type] -> (TidyEnv, [Type]) +tidyOpenTypes env tys = mapAccumL tidyOpenType env tys -isUnboxedType = isPrimType +tidyTopType :: Type -> Type +tidyTopType ty = tidyType emptyTidyEnv ty \end{code} -This is *not* right: it is a placeholder (ToDo 96/03 WDP): -\begin{code} -typePrimRep :: Type -> PrimRep -typePrimRep (SynTy _ _ ty) = typePrimRep ty -typePrimRep (AppTy ty _) = typePrimRep ty -typePrimRep (TyConTy tc _) - | isPrimTyCon tc = case (assocMaybe tc_primrep_list (uniqueOf tc)) of - Just xx -> xx - Nothing -> panic "Type.typePrimRep" -- pprPanic "typePrimRep:" (pprTyCon PprDebug tc) - - | otherwise = case maybeNewTyCon tc of - Just (tyvars, ty) | isPrimType ty -> typePrimRep ty - _ -> PtrRep -- Default - -typePrimRep _ = PtrRep -- the "default" - -tc_primrep_list - = [(addrPrimTyConKey, AddrRep) - ,(arrayPrimTyConKey, ArrayRep) - ,(byteArrayPrimTyConKey, ByteArrayRep) - ,(charPrimTyConKey, CharRep) - ,(doublePrimTyConKey, DoubleRep) - ,(floatPrimTyConKey, FloatRep) - ,(foreignObjPrimTyConKey, ForeignObjRep) - ,(intPrimTyConKey, IntRep) - ,(mutableArrayPrimTyConKey, ArrayRep) - ,(mutableByteArrayPrimTyConKey, ByteArrayRep) - ,(stablePtrPrimTyConKey, StablePtrRep) - ,(statePrimTyConKey, VoidRep) - ,(synchVarPrimTyConKey, PtrRep) - ,(voidTyConKey, VoidRep) - ,(wordPrimTyConKey, WordRep) - ] -\end{code} %************************************************************************ %* * -\subsection{Matching on types} +\subsection{Liftedness} %* * %************************************************************************ -Matching is a {\em unidirectional} process, matching a type against a -template (which is just a type with type variables in it). The -matcher assumes that there are no repeated type variables in the -template, so that it simply returns a mapping of type variables to -types. It also fails on nested foralls. +\begin{code} +isUnLiftedType :: Type -> Bool + -- isUnLiftedType returns True for forall'd unlifted types: + -- x :: forall a. Int# + -- I found bindings like these were getting floated to the top level. + -- They are pretty bogus types, mind you. It would be better never to + -- construct them + +isUnLiftedType (ForAllTy tv ty) = isUnLiftedType ty +isUnLiftedType (NoteTy _ ty) = isUnLiftedType ty +isUnLiftedType (TyConApp tc _) = isUnLiftedTyCon tc +isUnLiftedType (UsageTy _ ty) = isUnLiftedType ty +isUnLiftedType (SourceTy _) = False -- All source types are lifted +isUnLiftedType other = False + +isUnboxedTupleType :: Type -> Bool +isUnboxedTupleType ty = case splitTyConApp_maybe ty of + Just (tc, ty_args) -> isUnboxedTupleTyCon tc + other -> False + +-- Should only be applied to *types*; hence the assert +isAlgType :: Type -> Bool +isAlgType ty = case splitTyConApp_maybe ty of + Just (tc, ty_args) -> ASSERT( length ty_args == tyConArity tc ) + isAlgTyCon tc + other -> False +\end{code} -@matchTys@ matches corresponding elements of a list of templates and -types. +@isStrictType@ computes whether an argument (or let RHS) should +be computed strictly or lazily, based only on its type. +Works just like isUnLiftedType, except that it has a special case +for dictionaries. Since it takes account of ClassP, you might think +this function should be in TcType, but isStrictType is used by DataCon, +which is below TcType in the hierarchy, so it's convenient to put it here. \begin{code} -matchTy :: GenType t1 u1 -- Template - -> GenType t2 u2 -- Proposed instance of template - -> Maybe [(t1,GenType t2 u2)] -- Matching substitution - - -matchTys :: [GenType t1 u1] -- Templates - -> [GenType t2 u2] -- Proposed instance of template - -> Maybe ([(t1,GenType t2 u2)],-- Matching substitution - [GenType t2 u2]) -- Left over instance types - -matchTy ty1 ty2 = match ty1 ty2 (\s -> Just s) [] -matchTys tys1 tys2 = go [] tys1 tys2 - where - go s [] tys2 = Just (s,tys2) - go s (ty1:tys1) [] = trace "matchTys" Nothing - go s (ty1:tys1) (ty2:tys2) = match ty1 ty2 (\s' -> go s' tys1 tys2) s +isStrictType (ForAllTy tv ty) = isStrictType ty +isStrictType (NoteTy _ ty) = isStrictType ty +isStrictType (TyConApp tc _) = isUnLiftedTyCon tc +isStrictType (UsageTy _ ty) = isStrictType ty +isStrictType (SourceTy (ClassP clas _)) = opt_DictsStrict && not (isNewTyCon (classTyCon clas)) + -- We may be strict in dictionary types, but only if it + -- has more than one component. + -- [Being strict in a single-component dictionary risks + -- poking the dictionary component, which is wrong.] +isStrictType other = False \end{code} -@match@ is the main function. - \begin{code} -match :: GenType t1 u1 -> GenType t2 u2 -- Current match pair - -> ([(t1, GenType t2 u2)] -> Maybe result) -- Continuation - -> [(t1, GenType t2 u2)] -- Current substitution - -> Maybe result - -match (TyVarTy v) ty k = \s -> k ((v,ty) : s) -match (FunTy fun1 arg1 _) (FunTy fun2 arg2 _) k = match fun1 fun2 (match arg1 arg2 k) -match (AppTy fun1 arg1) (AppTy fun2 arg2) k = match fun1 fun2 (match arg1 arg2 k) -match (TyConTy con1 _) (TyConTy con2 _) k | con1 == con2 = k -match (DictTy clas1 ty1 _) (DictTy clas2 ty2 _) k | clas1 == clas2 = match ty1 ty2 k -match (SynTy _ _ ty1) ty2 k = match ty1 ty2 k -match ty1 (SynTy _ _ ty2) k = match ty1 ty2 k - - -- With type synonyms, we have to be careful for the exact - -- same reasons as in the unifier. Please see the - -- considerable commentary there before changing anything - -- here! (WDP 95/05) - --- Catch-all fails -match _ _ _ = \s -> Nothing +isPrimitiveType :: Type -> Bool +-- Returns types that are opaque to Haskell. +-- Most of these are unlifted, but now that we interact with .NET, we +-- may have primtive (foreign-imported) types that are lifted +isPrimitiveType ty = case splitTyConApp_maybe ty of + Just (tc, ty_args) -> ASSERT( length ty_args == tyConArity tc ) + isPrimTyCon tc + other -> False \end{code} + %************************************************************************ %* * -\subsection{Equality on types} +\subsection{Sequencing on types %* * %************************************************************************ -The functions eqSimpleTy and eqSimpleTheta are polymorphic in the types t -and u, but ONLY WORK FOR SIMPLE TYPES (ie. they panic if they see -dictionaries or polymorphic types). The function eqTy has a more -specific type, but does the `right thing' for all types. - \begin{code} -eqSimpleTheta :: (Eq t,Eq u) => - [(Class,GenType t u)] -> [(Class,GenType t u)] -> Bool - -eqSimpleTheta [] [] = True -eqSimpleTheta ((c1,t1):th1) ((c2,t2):th2) = - c1==c2 && t1 `eqSimpleTy` t2 && th1 `eqSimpleTheta` th2 -eqSimpleTheta other1 other2 = False +seqType :: Type -> () +seqType (TyVarTy tv) = tv `seq` () +seqType (AppTy t1 t2) = seqType t1 `seq` seqType t2 +seqType (FunTy t1 t2) = seqType t1 `seq` seqType t2 +seqType (NoteTy note t2) = seqNote note `seq` seqType t2 +seqType (SourceTy p) = seqPred p +seqType (TyConApp tc tys) = tc `seq` seqTypes tys +seqType (ForAllTy tv ty) = tv `seq` seqType ty +seqType (UsageTy u ty) = seqType u `seq` seqType ty + +seqTypes :: [Type] -> () +seqTypes [] = () +seqTypes (ty:tys) = seqType ty `seq` seqTypes tys + +seqNote :: TyNote -> () +seqNote (SynNote ty) = seqType ty +seqNote (FTVNote set) = sizeUniqSet set `seq` () + +seqPred :: SourceType -> () +seqPred (ClassP c tys) = c `seq` seqTypes tys +seqPred (NType tc tys) = tc `seq` seqTypes tys +seqPred (IParam n ty) = n `seq` seqType ty \end{code} -\begin{code} -eqSimpleTy :: (Eq t,Eq u) => GenType t u -> GenType t u -> Bool - -(TyVarTy tv1) `eqSimpleTy` (TyVarTy tv2) = - tv1 == tv2 -(AppTy f1 a1) `eqSimpleTy` (AppTy f2 a2) = - f1 `eqSimpleTy` f2 && a1 `eqSimpleTy` a2 -(TyConTy tc1 u1) `eqSimpleTy` (TyConTy tc2 u2) = - tc1 == tc2 --ToDo: later: && u1 == u2 - -(FunTy f1 a1 u1) `eqSimpleTy` (FunTy f2 a2 u2) = - f1 `eqSimpleTy` f2 && a1 `eqSimpleTy` a2 && u1 == u2 -(FunTy f1 a1 u1) `eqSimpleTy` t2 = - -- Expand t1 just in case t2 matches that version - (AppTy (AppTy (TyConTy mkFunTyCon u1) f1) a1) `eqSimpleTy` t2 -t1 `eqSimpleTy` (FunTy f2 a2 u2) = - -- Expand t2 just in case t1 matches that version - t1 `eqSimpleTy` (AppTy (AppTy (TyConTy mkFunTyCon u2) f2) a2) - -(SynTy tc1 ts1 t1) `eqSimpleTy` (SynTy tc2 ts2 t2) = - (tc1 == tc2 && and (zipWith eqSimpleTy ts1 ts2) && length ts1 == length ts2) - || t1 `eqSimpleTy` t2 -(SynTy _ _ t1) `eqSimpleTy` t2 = - t1 `eqSimpleTy` t2 -- Expand the abbrevation and try again -t1 `eqSimpleTy` (SynTy _ _ t2) = - t1 `eqSimpleTy` t2 -- Expand the abbrevation and try again - -(DictTy _ _ _) `eqSimpleTy` _ = panic "eqSimpleTy: got DictTy" -_ `eqSimpleTy` (DictTy _ _ _) = panic "eqSimpleTy: got DictTy" - -(ForAllTy _ _) `eqSimpleTy` _ = panic "eqSimpleTy: got ForAllTy" -_ `eqSimpleTy` (ForAllTy _ _) = panic "eqSimpleTy: got ForAllTy" - -(ForAllUsageTy _ _ _) `eqSimpleTy` _ = panic "eqSimpleTy: got ForAllUsageTy" -_ `eqSimpleTy` (ForAllUsageTy _ _ _) = panic "eqSimpleTy: got ForAllUsageTy" - -_ `eqSimpleTy` _ = False -\end{code} -Types are ordered so we can sort on types in the renamer etc. DNT: Since -this class is also used in CoreLint and other such places, we DO expand out -Fun/Syn/Dict types (if necessary). +%************************************************************************ +%* * +\subsection{Equality on types} +%* * +%************************************************************************ -\begin{code} -eqTy :: Type -> Type -> Bool +Comparison; don't use instances so that we know where it happens. +Look through newtypes but not usage types. -eqTy t1 t2 = - eq nullTyVarEnv nullUVarEnv t1 t2 - where - eq tve uve (TyVarTy tv1) (TyVarTy tv2) = - tv1 == tv2 || - case (lookupTyVarEnv tve tv1) of - Just tv -> tv == tv2 - Nothing -> False - eq tve uve (AppTy f1 a1) (AppTy f2 a2) = - eq tve uve f1 f2 && eq tve uve a1 a2 - eq tve uve (TyConTy tc1 u1) (TyConTy tc2 u2) = - tc1 == tc2 -- ToDo: LATER: && eqUsage uve u1 u2 - - eq tve uve (FunTy f1 a1 u1) (FunTy f2 a2 u2) = - eq tve uve f1 f2 && eq tve uve a1 a2 && eqUsage uve u1 u2 - eq tve uve (FunTy f1 a1 u1) t2 = - -- Expand t1 just in case t2 matches that version - eq tve uve (AppTy (AppTy (TyConTy mkFunTyCon u1) f1) a1) t2 - eq tve uve t1 (FunTy f2 a2 u2) = - -- Expand t2 just in case t1 matches that version - eq tve uve t1 (AppTy (AppTy (TyConTy mkFunTyCon u2) f2) a2) - - eq tve uve (DictTy c1 t1 u1) (DictTy c2 t2 u2) - | c1 == c2 - = eq tve uve t1 t2 && eqUsage uve u1 u2 - -- NB we use a guard for c1==c2 so that if they aren't equal we - -- fall through into expanding the type. Why? Because brain-dead - -- people might write - -- class Foo a => Baz a where {} - -- and that means that a Foo dictionary and a Baz dictionary are identical - -- Sigh. Let's hope we don't spend too much time in here! - - eq tve uve t1@(DictTy _ _ _) t2 = - eq tve uve (expandTy t1) t2 -- Expand the dictionary and try again - eq tve uve t1 t2@(DictTy _ _ _) = - eq tve uve t1 (expandTy t2) -- Expand the dictionary and try again - - eq tve uve (SynTy tc1 ts1 t1) (SynTy tc2 ts2 t2) = - (tc1 == tc2 && and (zipWith (eq tve uve) ts1 ts2) && length ts1 == length ts2) - || eq tve uve t1 t2 - eq tve uve (SynTy _ _ t1) t2 = - eq tve uve t1 t2 -- Expand the abbrevation and try again - eq tve uve t1 (SynTy _ _ t2) = - eq tve uve t1 t2 -- Expand the abbrevation and try again - - eq tve uve (ForAllTy tv1 t1) (ForAllTy tv2 t2) = - eq (addOneToTyVarEnv tve tv1 tv2) uve t1 t2 - eq tve uve (ForAllUsageTy u1 b1 t1) (ForAllUsageTy u2 b2 t2) = - eqBounds uve b1 b2 && eq tve (addOneToUVarEnv uve u1 u2) t1 t2 - - eq _ _ _ _ = False - - eqBounds uve [] [] = True - eqBounds uve (u1:b1) (u2:b2) = eqUVar uve u1 u2 && eqBounds uve b1 b2 - eqBounds uve _ _ = False +\begin{code} +eqType t1 t2 = eq_ty emptyVarEnv t1 t2 +eqKind = eqType -- No worries about looking +eqUsage = eqType -- through source types for these two + +-- Look through Notes +eq_ty env (NoteTy _ t1) t2 = eq_ty env t1 t2 +eq_ty env t1 (NoteTy _ t2) = eq_ty env t1 t2 + +-- Look through SourceTy. This is where the looping danger comes from +eq_ty env (SourceTy sty1) t2 = eq_ty env (sourceTypeRep sty1) t2 +eq_ty env t1 (SourceTy sty2) = eq_ty env t1 (sourceTypeRep sty2) + +-- The rest is plain sailing +eq_ty env (TyVarTy tv1) (TyVarTy tv2) = case lookupVarEnv env tv1 of + Just tv1a -> tv1a == tv2 + Nothing -> tv1 == tv2 +eq_ty env (ForAllTy tv1 t1) (ForAllTy tv2 t2) + | tv1 == tv2 = eq_ty (delVarEnv env tv1) t1 t2 + | otherwise = eq_ty (extendVarEnv env tv1 tv2) t1 t2 +eq_ty env (AppTy s1 t1) (AppTy s2 t2) = (eq_ty env s1 s2) && (eq_ty env t1 t2) +eq_ty env (FunTy s1 t1) (FunTy s2 t2) = (eq_ty env s1 s2) && (eq_ty env t1 t2) +eq_ty env (UsageTy _ t1) (UsageTy _ t2) = eq_ty env t1 t2 +eq_ty env (TyConApp tc1 tys1) (TyConApp tc2 tys2) = (tc1 == tc2) && (eq_tys env tys1 tys2) +eq_ty env t1 t2 = False + +eq_tys env [] [] = True +eq_tys env (t1:tys1) (t2:tys2) = (eq_ty env t1 t2) && (eq_tys env tys1 tys2) +eq_tys env tys1 tys2 = False \end{code} +