X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypes%2FType.lhs;h=c7e5fa250901254842eab866d7a2e7d0edde5851;hb=423d477bfecd490de1449c59325c8776f91d7aac;hp=d419223d1c4060402a2e67e2d4957e5e78bad7bb;hpb=38f258e08a3415b0c129779b2133595ea1fb8921;p=ghc-hetmet.git diff --git a/ghc/compiler/types/Type.lhs b/ghc/compiler/types/Type.lhs index d419223..c7e5fa2 100644 --- a/ghc/compiler/types/Type.lhs +++ b/ghc/compiler/types/Type.lhs @@ -1,1038 +1,920 @@ -\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, splitAppTys, - mkFunTy, mkFunTys, - splitFunTy, splitFunTyExpandingDicts, splitFunTyExpandingDictsAndPeeking, - getFunTy_maybe, getFunTyExpandingDicts_maybe, - mkTyConTy, getTyCon_maybe, applyTyCon, - mkSynTy, - mkForAllTy, mkForAllTys, getForAllTy_maybe, getForAllTyExpandingDicts_maybe, - splitForAllTy, splitForAllTyExpandingDicts, - mkForAllUsageTy, getForAllUsageTy, - applyTy, specialiseTy, -#ifdef DEBUG - expandTy, -- only let out for debugging (ToDo: rm?) -#endif - isPrimType, isUnboxedType, typePrimRep, - - SYN_IE(RhoType), SYN_IE(SigmaType), SYN_IE(ThetaType), - mkDictTy, - mkRhoTy, splitRhoTy, mkTheta, isDictTy, - mkSigmaTy, splitSigmaTy, - - maybeAppTyCon, getAppTyCon, - maybeAppDataTyCon, getAppDataTyCon, getAppSpecDataTyCon, - maybeAppDataTyConExpandingDicts, maybeAppSpecDataTyConExpandingDicts, - getAppDataTyConExpandingDicts, getAppSpecDataTyConExpandingDicts, - maybeBoxedPrimType, - - matchTy, matchTys, eqTy, eqSimpleTy, eqSimpleTheta, - - instantiateTy, instantiateTauTy, instantiateUsage, - applyTypeEnvToTy, - - isTauTy, - - tyVarsOfType, tyVarsOfTypes, namesOfType, typeKind, - showTypeCategory - ) where + -- re-exports from TypeRep + TyThing(..), Type, PredType(..), ThetaType, TyVarSubst, + funTyCon, -IMP_Ubiq() -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201 -IMPORT_DELOOPER(IdLoop) -- for paranoia checking -IMPORT_DELOOPER(TyLoop) ---IMPORT_DELOOPER(PrelLoop) -- for paranoia checking -#else -import {-# SOURCE #-} Id ( Id, dataConArgTys ) -import {-# SOURCE #-} TysPrim ( voidTy ) -import {-# SOURCE #-} TysWiredIn ( tupleTyCon ) -#endif + -- Re-exports from Kind + module Kind, --- friends: -import Class ( classDictArgTys, GenClass{-instances-}, SYN_IE(Class) ) -import Kind ( mkBoxedTypeKind, resultKind, notArrowKind, Kind ) -import TyCon ( mkFunTyCon, isFunTyCon, isEnumerationTyCon, isTupleTyCon, maybeTyConSingleCon, - isPrimTyCon, isAlgTyCon, 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 - ) + -- Re-exports from TyCon + PrimRep(..), --- 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-} - ) -\end{code} + mkTyVarTy, mkTyVarTys, getTyVar, getTyVar_maybe, isTyVarTy, -Data types -~~~~~~~~~~ + mkAppTy, mkAppTys, splitAppTy, splitAppTys, splitAppTy_maybe, -\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} + mkFunTy, mkFunTys, splitFunTy, splitFunTy_maybe, splitFunTys, + funResultTy, funArgTy, zipFunTys, isFunTy, -\begin{code} -type RhoType = Type -type TauType = Type -type ThetaType = [(Class, Type)] -type SigmaType = Type -\end{code} + mkGenTyConApp, mkTyConApp, mkTyConTy, + tyConAppTyCon, tyConAppArgs, + splitTyConApp_maybe, splitTyConApp, + mkSynTy, -Notes on type synonyms -~~~~~~~~~~~~~~~~~~~~~~ -The various "split" functions (splitFunTy, splitRhoTy, splitForAllTy) try -to return type synonyms whereever possible. Thus + repType, typePrimRep, - type Foo a = a -> a + mkForAllTy, mkForAllTys, splitForAllTy_maybe, splitForAllTys, + applyTy, applyTys, isForAllTy, dropForAlls, -we want - splitFunTys (a -> Foo a) = ([a], Foo a) -not ([a], a -> a) + -- Source types + predTypeRep, mkPredTy, mkPredTys, -The reason is that we then get better (shorter) type signatures in -interfaces. Notably this plays a role in tcTySigs in TcBinds.lhs. + -- Newtypes + splitRecNewType_maybe, + -- Lifting and boxity + isUnLiftedType, isUnboxedTupleType, isAlgType, isPrimitiveType, + isStrictType, isStrictPred, -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 + -- Free variables + tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tyVarsOfTheta, + typeKind, addFreeTyVars, -getTyVar :: String -> GenType t u -> t -getTyVar msg (TyVarTy tv) = tv -getTyVar msg (SynTy _ _ t) = getTyVar msg t -getTyVar msg other = panic ("getTyVar: " ++ msg) + -- Tidying up for printing + tidyType, tidyTypes, + tidyOpenType, tidyOpenTypes, + tidyTyVarBndr, tidyFreeTyVars, + tidyOpenTyVar, tidyOpenTyVars, + tidyTopType, tidyPred, -getTyVar_maybe :: GenType t u -> Maybe t -getTyVar_maybe (TyVarTy tv) = Just tv -getTyVar_maybe (SynTy _ _ t) = getTyVar_maybe t -getTyVar_maybe other = Nothing + -- Comparison + eqType, -isTyVarTy :: GenType t u -> Bool -isTyVarTy (TyVarTy tv) = True -isTyVarTy (SynTy _ _ t) = isTyVarTy t -isTyVarTy other = False -\end{code} + -- Seq + seqType, seqTypes, -\begin{code} -mkAppTy = AppTy + -- Pretty-printing + pprType, pprParendType, + pprPred, pprTheta, pprThetaArrow, pprClassPred + ) where -mkAppTys :: GenType t u -> [GenType t u] -> GenType t u -mkAppTys t ts = foldl AppTy t ts +#include "HsVersions.h" -splitAppTy :: GenType t u -> (GenType t u, GenType t u) -splitAppTy (AppTy t arg) = (t,arg) -splitAppTy (SynTy _ _ t) = splitAppTy t -splitAppTy other = panic "splitAppTy" +-- We import the representation and primitive functions from TypeRep. +-- Many things are reexported, but not the representation! -splitAppTys :: GenType t u -> (GenType t u, [GenType t u]) -splitAppTys 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) -\end{code} +import TypeRep -\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 t - = go t t - where - -- See notes on type synonyms above - go syn_t (FunTy arg result _) = Just (arg,result) - go syn_t (AppTy (AppTy (TyConTy tycon _) arg) res) - | isFunTyCon tycon = Just (arg, res) - go syn_t (SynTy _ _ t) = go syn_t t - go syn_t 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 - - -{- This is a truly disgusting bit of code. - It's used by the code generator to look at the rep of a newtype. - The code gen will have thrown away coercions involving that newtype, so - this is the other side of the coin. - Gruesome in the extreme. --} - -getFunTyExpandingDicts_maybe peek other - | not peek = Nothing -- that was easy - | otherwise - = case (maybeAppTyCon other) of - Just (tc, arg_tys) - | isNewTyCon tc && not (null data_cons) - -> getFunTyExpandingDicts_maybe peek inside_ty - where - data_cons = tyConDataCons tc - [the_con] = data_cons - [inside_ty] = dataConArgTys the_con arg_tys - - other -> Nothing - - -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 Why??? Nuked SLPJ May 97. We may not know the - -- rep of an abstractly imported newtype - -- foralls - -- expanding dictionary reps - -- synonyms, of course - -split_fun_ty get t = go t [] - where - go t ts = case (get t) of - Just (arg,res) -> go res (arg:ts) - Nothing -> (reverse ts, t) +-- Other imports: + +import {-# SOURCE #-} Subst ( substTyWith ) + +-- friends: +import Kind +import Var ( TyVar, tyVarKind, tyVarName, setTyVarName ) +import VarEnv +import VarSet + +import Name ( NamedThing(..), mkInternalName, tidyOccName ) +import Class ( Class, classTyCon ) +import TyCon ( TyCon, isRecursiveTyCon, isPrimTyCon, + isUnboxedTupleTyCon, isUnLiftedTyCon, + isFunTyCon, isNewTyCon, newTyConRep, newTyConRhs, + isAlgTyCon, isSynTyCon, tyConArity, + tyConKind, getSynTyConDefn, PrimRep(..), tyConPrimRep, + ) + +-- others +import CmdLineOpts ( opt_DictsStrict ) +import SrcLoc ( noSrcLoc ) +import Unique ( Uniquable(..) ) +import Util ( mapAccumL, seqList, lengthIs, snocView ) +import Outputable +import UniqSet ( sizeUniqSet ) -- Should come via VarSet +import Maybe ( isJust ) \end{code} + +%************************************************************************ +%* * +\subsection{Constructor-specific functions} +%* * +%************************************************************************ + + +--------------------------------------------------------------------- + TyVarTy + ~~~~~~~ \begin{code} --- NB applyTyCon puts in usageOmega, for now at least -mkTyConTy tycon - = ASSERT(not (isSynTyCon tycon)) - TyConTy tycon usageOmega +mkTyVarTy :: TyVar -> Type +mkTyVarTy = TyVarTy + +mkTyVarTys :: [TyVar] -> [Type] +mkTyVarTys = map mkTyVarTy -- a common use of mkTyVarTy -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 +getTyVar :: String -> Type -> TyVar +getTyVar msg ty = case getTyVar_maybe ty of + Just tv -> tv + Nothing -> panic ("getTyVar: " ++ msg) -getTyCon_maybe :: GenType t u -> Maybe TyCon +isTyVarTy :: Type -> Bool +isTyVarTy ty = isJust (getTyVar_maybe ty) -getTyCon_maybe (TyConTy tycon _) = Just tycon -getTyCon_maybe (SynTy _ _ t) = getTyCon_maybe t -getTyCon_maybe other_ty = Nothing +getTyVar_maybe :: Type -> Maybe TyVar +getTyVar_maybe (TyVarTy tv) = Just tv +getTyVar_maybe (NoteTy _ t) = getTyVar_maybe t +getTyVar_maybe (PredTy p) = getTyVar_maybe (predTypeRep p) +getTyVar_maybe (NewTcApp tc tys) = getTyVar_maybe (newTypeRep tc tys) +getTyVar_maybe other = Nothing \end{code} + +--------------------------------------------------------------------- + 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. + \begin{code} -specialiseTy :: Type -- The type of the Id of which the SpecId - -- is a specialised version - -> [Maybe Type] -- The types at which it is specialised - -> Int -- Number of leading dictionary args to ignore - -> Type - -specialiseTy main_ty maybe_tys dicts_to_ignore - = --false:ASSERT(isTauTy tau) TauType?? - mkSigmaTy remaining_tyvars - (instantiateThetaTy inst_env remaining_theta) - (instantiateTauTy inst_env tau) +mkAppTy orig_ty1 orig_ty2 + = mk_app orig_ty1 where - (tyvars, theta, tau) = splitSigmaTy main_ty -- A prefix of, but usually all, - -- the theta is discarded! - remaining_theta = drop dicts_to_ignore theta - tyvars_and_maybe_tys = tyvars `zip` maybe_tys - remaining_tyvars = [tyvar | (tyvar, Nothing) <- tyvars_and_maybe_tys] - inst_env = [(tyvar,ty) | (tyvar, Just ty) <- tyvars_and_maybe_tys] + mk_app (NoteTy _ ty1) = mk_app ty1 + mk_app (NewTcApp tc tys) = NewTcApp tc (tys ++ [orig_ty2]) + mk_app (TyConApp tc tys) = mkGenTyConApp tc (tys ++ [orig_ty2]) + mk_app ty1 = AppTy orig_ty1 orig_ty2 + -- We call mkGenTyConApp because the TyConApp could be an + -- under-saturated type synonym. GHC allows that; e.g. + -- type Foo k = k a -> k a + -- type Id x = x + -- foo :: Foo Id -> Foo Id + -- + -- Here Id is partially applied in the type sig for Foo, + -- but once the type synonyms are expanded all is well + +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 + = mk_app orig_ty1 + where + mk_app (NoteTy _ ty1) = mk_app ty1 + mk_app (NewTcApp tc tys) = NewTcApp tc (tys ++ orig_tys2) + mk_app (TyConApp tc tys) = mkTyConApp tc (tys ++ orig_tys2) + -- Use mkTyConApp in case tc is (->) + mk_app ty1 = foldl AppTy orig_ty1 orig_tys2 + +splitAppTy_maybe :: Type -> Maybe (Type, Type) +splitAppTy_maybe (FunTy ty1 ty2) = Just (TyConApp funTyCon [ty1], ty2) +splitAppTy_maybe (AppTy ty1 ty2) = Just (ty1, ty2) +splitAppTy_maybe (NoteTy _ ty) = splitAppTy_maybe ty +splitAppTy_maybe (PredTy p) = splitAppTy_maybe (predTypeRep p) +splitAppTy_maybe (NewTcApp tc tys) = splitAppTy_maybe (newTypeRep tc tys) +splitAppTy_maybe (TyConApp tc tys) = case snocView tys of + Nothing -> Nothing + Just (tys',ty') -> Just (mkGenTyConApp tc tys', ty') + -- mkGenTyConApp just in case the tc is a newtype + +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 + 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 (PredTy p) args = split orig_ty (predTypeRep p) args + split orig_ty (NewTcApp tc tc_args) args = split orig_ty (newTypeRep tc tc_args) args + split orig_ty (TyConApp tc tc_args) args = (mkGenTyConApp tc [], tc_args ++ args) + -- mkGenTyConApp just in case the tc is a newtype + split orig_ty (FunTy ty1 ty2) args = ASSERT( null args ) + (TyConApp funTyCon [], [ty1,ty2]) + split orig_ty ty args = (orig_ty, args) \end{code} + +--------------------------------------------------------------------- + FunTy + ~~~~~ + \begin{code} -mkSynTy syn_tycon tys - = ASSERT(isSynTyCon syn_tycon) - SynTy syn_tycon tys (instantiateTauTy (zipEqual "mkSynTy" tyvars tys) body) +mkFunTy :: Type -> Type -> Type +mkFunTy arg res = FunTy arg res + +mkFunTys :: [Type] -> Type -> Type +mkFunTys tys ty = foldr FunTy ty tys + +isFunTy :: Type -> Bool +isFunTy ty = isJust (splitFunTy_maybe ty) + +splitFunTy :: Type -> (Type, Type) +splitFunTy (FunTy arg res) = (arg, res) +splitFunTy (NoteTy _ ty) = splitFunTy ty +splitFunTy (PredTy p) = splitFunTy (predTypeRep p) +splitFunTy (NewTcApp tc tys) = splitFunTy (newTypeRep tc tys) +splitFunTy other = pprPanic "splitFunTy" (ppr other) + +splitFunTy_maybe :: Type -> Maybe (Type, Type) +splitFunTy_maybe (FunTy arg res) = Just (arg, res) +splitFunTy_maybe (NoteTy _ ty) = splitFunTy_maybe ty +splitFunTy_maybe (PredTy p) = splitFunTy_maybe (predTypeRep p) +splitFunTy_maybe (NewTcApp tc tys) = splitFunTy_maybe (newTypeRep tc tys) +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 (PredTy p) = split args orig_ty (predTypeRep p) + split args orig_ty (NewTcApp tc tys) = split args orig_ty (newTypeRep tc tys) + 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 - (tyvars, body) = getSynTyConDefn syn_tycon + 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 (PredTy p) = split acc xs nty (predTypeRep p) + split acc xs nty (NewTcApp tc tys) = split acc xs nty (newTypeRep tc tys) + split acc (x:xs) nty ty = pprPanic "zipFunTys" (ppr orig_xs <+> ppr orig_ty) + +funResultTy :: Type -> Type +funResultTy (FunTy arg res) = res +funResultTy (NoteTy _ ty) = funResultTy ty +funResultTy (PredTy p) = funResultTy (predTypeRep p) +funResultTy (NewTcApp tc tys) = funResultTy (newTypeRep tc tys) +funResultTy ty = pprPanic "funResultTy" (ppr ty) + +funArgTy :: Type -> Type +funArgTy (FunTy arg res) = arg +funArgTy (NoteTy _ ty) = funArgTy ty +funArgTy (PredTy p) = funArgTy (predTypeRep p) +funArgTy (NewTcApp tc tys) = funArgTy (newTypeRep tc tys) +funArgTy ty = pprPanic "funArgTy" (ppr ty) \end{code} -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 -\end{code} -Rho stuff -~~~~~~~~~ -NB mkRhoTy and mkDictTy put in usageOmega, for now at least +--------------------------------------------------------------------- + TyConApp + ~~~~~~~~ +@mkTyConApp@ is a key function, because it builds a TyConApp, FunTy or PredTy, +as apppropriate. \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 - -splitRhoTy :: GenType t u -> ([(Class,GenType t u)], GenType t u) -splitRhoTy t = - go t t [] - where - -- See notes on type synonyms above - go syn_t (FunTy (DictTy c t _) r _) ts = go r r ((c,t):ts) - go syn_t (AppTy (AppTy (TyConTy tycon _) (DictTy c t _)) r) ts - | isFunTyCon tycon - = go r r ((c,t):ts) - go syn_t (SynTy _ _ t) ts = go syn_t t ts - go syn_t t ts = (reverse ts, syn_t) - - -mkTheta :: [Type] -> ThetaType - -- recover a ThetaType from the types of some dictionaries -mkTheta dict_tys - = map cvt dict_tys - where - cvt (DictTy clas ty _) = (clas, ty) - cvt other = panic "Type.mkTheta" -- pprPanic "mkTheta:" (pprType PprDebug other) +mkGenTyConApp :: TyCon -> [Type] -> Type +mkGenTyConApp tc tys + | isSynTyCon tc = mkSynTy tc tys + | otherwise = mkTyConApp tc tys -isDictTy (DictTy _ _ _) = True -isDictTy (SynTy _ _ t) = isDictTy t -isDictTy _ = False -\end{code} +mkTyConApp :: TyCon -> [Type] -> Type +-- Assumes TyCon is not a SynTyCon; use mkSynTy instead for those +mkTyConApp tycon tys + | isFunTyCon tycon, [ty1,ty2] <- tys + = FunTy ty1 ty2 + | isNewTyCon tycon + = NewTcApp tycon tys -Forall stuff -~~~~~~~~~~~~ -\begin{code} -mkForAllTy = ForAllTy + | otherwise + = ASSERT(not (isSynTyCon tycon)) + TyConApp tycon tys -mkForAllTys :: [t] -> GenType t u -> GenType t u -mkForAllTys tyvars ty = foldr ForAllTy ty tyvars +mkTyConTy :: TyCon -> Type +mkTyConTy tycon = mkTyConApp tycon [] -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 t [] - where - -- See notes on type synonyms above - go syn_t (ForAllTy tv t) tvs = go t t (tv:tvs) - go syn_t (SynTy _ _ t) tvs = go syn_t t tvs - go syn_t t tvs = (reverse tvs, syn_t) - -splitForAllTyExpandingDicts :: Type -> ([TyVar], Type) -splitForAllTyExpandingDicts ty - = go [] ty - where - go tvs ty = case getForAllTyExpandingDicts_maybe ty of - Just (tv, ty') -> go (tv:tvs) ty' - Nothing -> (reverse tvs, ty) -\end{code} +-- splitTyConApp "looks through" synonyms, because they don't +-- mean a distinct type, but all other type-constructor applications +-- including functions are returned as Just .. -\begin{code} -mkForAllUsageTy :: u -> [u] -> GenType t u -> GenType t u -mkForAllUsageTy = ForAllUsageTy +tyConAppTyCon :: Type -> TyCon +tyConAppTyCon ty = fst (splitTyConApp ty) + +tyConAppArgs :: Type -> [Type] +tyConAppArgs ty = snd (splitTyConApp ty) -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 +splitTyConApp :: Type -> (TyCon, [Type]) +splitTyConApp ty = case splitTyConApp_maybe ty of + Just stuff -> stuff + Nothing -> pprPanic "splitTyConApp" (ppr ty) + +splitTyConApp_maybe :: Type -> Maybe (TyCon, [Type]) +splitTyConApp_maybe (TyConApp tc tys) = Just (tc, tys) +splitTyConApp_maybe (FunTy arg res) = Just (funTyCon, [arg,res]) +splitTyConApp_maybe (NoteTy _ ty) = splitTyConApp_maybe ty +splitTyConApp_maybe (PredTy p) = splitTyConApp_maybe (predTypeRep p) +splitTyConApp_maybe (NewTcApp tc tys) = splitTyConApp_maybe (newTypeRep tc tys) +splitTyConApp_maybe other = Nothing \end{code} -Applied tycons (includes FunTyCons) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +--------------------------------------------------------------------- + SynTy + ~~~~~ + \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) +mkSynTy tycon tys + | n_args == arity -- Exactly saturated + = mk_syn tys + | n_args > arity -- Over-saturated + = case splitAt arity tys of { (as,bs) -> mkAppTys (mk_syn as) bs } + -- Its important to use mkAppTys, rather than (foldl AppTy), + -- because (mk_syn as) might well return a partially-applied + -- type constructor; indeed, usually will! + | 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 - (app_ty, arg_tys) = splitAppTys ty + 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} -getAppTyCon - :: GenType tyvar uvar - -> (TyCon, -- the type constructor - [GenType tyvar uvar]) -- types to which it is applied +Notes on type synonyms +~~~~~~~~~~~~~~~~~~~~~~ +The various "split" functions (splitFunTy, splitRhoTy, splitForAllTy) try +to return type synonyms whereever possible. Thus -getAppTyCon ty - = case maybeAppTyCon ty of - Just stuff -> stuff -#ifdef DEBUG - Nothing -> panic "Type.getAppTyCon" -- (ppr PprShowAll ty) -#endif -\end{code} + type Foo a = a -> a -Applied data tycons (give back constrs) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Nota Bene: all these functions suceed for @newtype@ applications too! +we want + splitFunTys (a -> Foo a) = ([a], Foo a) +not ([a], a -> a) -\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]) - -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 - - -maybe_app_data_tycon expand ty - = let - expanded_ty = expand ty - (app_ty, arg_tys) = splitAppTys expanded_ty - in - case (getTyCon_maybe app_ty) of - Just tycon | isAlgTyCon tycon && -- NB "Alg"; succeeds for newtype too - 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 - - -maybeBoxedPrimType :: Type -> Maybe (Id, Type) - -maybeBoxedPrimType ty - = case (maybeAppDataTyCon ty) of -- Data type, - Just (tycon, tys_applied, [data_con]) | isDataTyCon tycon -- 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} +The reason is that we then get better (shorter) type signatures in +interfaces. Notably this plays a role in tcTySigs in TcBinds.lhs. -\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 - -mkSigmaTy tyvars theta tau = mkForAllTys tyvars (mkRhoTy theta tau) -\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. -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 +repType :: Type -> Type +-- Only applied to types of kind *; hence tycons are saturated +repType (ForAllTy _ ty) = repType ty +repType (NoteTy _ ty) = repType ty +repType (PredTy p) = repType (predTypeRep p) +repType (NewTcApp tc tys) = ASSERT( tys `lengthIs` tyConArity tc ) + repType (new_type_rep tc tys) +repType ty = ty + + +-- ToDo: this could be moved to the code generator, using splitTyConApp instead +-- of inspecting the type directly. +typePrimRep :: Type -> PrimRep +typePrimRep ty = case repType ty of + TyConApp tc _ -> tyConPrimRep tc + FunTy _ _ -> PtrRep + AppTy _ _ -> PtrRep -- See note below + TyVarTy _ -> PtrRep + other -> pprPanic "typePrimRep" (ppr ty) + -- Types of the form 'f a' must be of kind *, not *#, so + -- we are guaranteed that they are represented by pointers. + -- The reason is that f must have kind *->*, not *->*#, because + -- (we claim) there is no way to constrain f's kind any other + -- way. + +-- new_type_rep doesn't ask any questions: +-- it just expands newtype, whether recursive or not +new_type_rep new_tycon tys = ASSERT( tys `lengthIs` tyConArity new_tycon ) + case newTyConRep new_tycon of + (tvs, rep_ty) -> substTyWith tvs tys rep_ty \end{code} -Free variables of a type -~~~~~~~~~~~~~~~~~~~~~~~~ +--------------------------------------------------------------------- + ForAllTy + ~~~~~~~~ + \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" +mkForAllTy :: TyVar -> Type -> Type +mkForAllTy tyvar ty + = mkForAllTys [tyvar] ty + +mkForAllTys :: [TyVar] -> Type -> Type +mkForAllTys tyvars ty = foldr ForAllTy ty tyvars + +isForAllTy :: Type -> Bool +isForAllTy (NoteTy _ ty) = isForAllTy ty +isForAllTy (ForAllTy _ _) = True +isForAllTy other_ty = False + +splitForAllTy_maybe :: Type -> Maybe (TyVar, Type) +splitForAllTy_maybe ty = splitFAT_m ty + where + splitFAT_m (NoteTy _ ty) = splitFAT_m ty + splitFAT_m (PredTy p) = splitFAT_m (predTypeRep p) + splitFAT_m (NewTcApp tc tys) = splitFAT_m (newTypeRep tc tys) + splitFAT_m (ForAllTy tyvar ty) = Just(tyvar, 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 (PredTy p) tvs = split orig_ty (predTypeRep p) tvs + split orig_ty (NewTcApp tc tys) tvs = split orig_ty (newTypeRep tc tys) tvs + split orig_ty t tvs = (reverse tvs, orig_ty) + +dropForAlls :: Type -> Type +dropForAlls ty = snd (splitForAllTys ty) \end{code} +-- (mkPiType now in CoreUtils) -Instantiating a type -~~~~~~~~~~~~~~~~~~~~ -\begin{code} --- applyTy :: GenType (GenTyVar flexi) uvar --- -> GenType (GenTyVar flexi) uvar --- -> GenType (GenTyVar flexi) uvar +applyTy, applyTys +~~~~~~~~~~~~~~~~~ +Instantiate a for-all type with one or more type arguments. +Used when we have a polymorphic function applied to type args: + f t1 t2 +Then we use (applyTys type-of-f [t1,t2]) to compute the type of +the expression. +\begin{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 (PredTy p) arg = applyTy (predTypeRep p) arg +applyTy (NewTcApp tc tys) arg = applyTy (newTypeRep tc tys) arg +applyTy (NoteTy _ fun) arg = applyTy fun arg +applyTy (ForAllTy tv ty) arg = substTyWith [tv] [arg] ty applyTy other arg = panic "applyTy" + +applyTys :: Type -> [Type] -> Type +-- This function is interesting because +-- a) the function may have more for-alls than there are args +-- b) less obviously, it may have fewer for-alls +-- For case (b) think of +-- applyTys (forall a.a) [forall b.b, Int] +-- This really can happen, via dressing up polymorphic types with newtype +-- clothing. Here's an example: +-- newtype R = R (forall a. a->a) +-- foo = case undefined :: R of +-- R f -> f () + +applyTys orig_fun_ty [] = orig_fun_ty +applyTys orig_fun_ty arg_tys + | n_tvs == n_args -- The vastly common case + = substTyWith tvs arg_tys rho_ty + | n_tvs > n_args -- Too many for-alls + = substTyWith (take n_args tvs) arg_tys + (mkForAllTys (drop n_args tvs) rho_ty) + | otherwise -- Too many type args + = ASSERT2( n_tvs > 0, ppr orig_fun_ty ) -- Zero case gives infnite loop! + applyTys (substTyWith tvs (take n_tvs arg_tys) rho_ty) + (drop n_tvs arg_tys) + where + (tvs, rho_ty) = splitForAllTys orig_fun_ty + n_tvs = length tvs + n_args = length arg_tys \end{code} -\begin{code} -instantiateTy :: [(GenTyVar flexi, GenType (GenTyVar flexi) uvar)] - -> GenType (GenTyVar flexi) uvar - -> GenType (GenTyVar flexi) uvar -instantiateTauTy :: Eq tv => - [(tv, GenType tv' u)] - -> GenType tv u - -> GenType tv' u +%************************************************************************ +%* * +\subsection{Source types} +%* * +%************************************************************************ -applyTypeEnvToTy :: TyVarEnv Type -> SigmaType -> SigmaType +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. --- 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 +Source types are always lifted. -instant_help ty lookup_tv deflt_tv choose_tycon - if_usage if_forall bound_forall_tv_BAD deflt_forall_tv - = 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 [] ty = 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" - -instantiateThetaTy tenv theta - = [(clas,instantiateTauTy tenv ty) | (clas,ty) <- theta] - --- 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 +The key function is predTypeRep which gives the representation of a source type: -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 +\begin{code} +mkPredTy :: PredType -> Type +mkPredTy pred = PredTy pred + +mkPredTys :: ThetaType -> [Type] +mkPredTys preds = map PredTy preds + +predTypeRep :: PredType -> Type +-- Convert a PredType to its "representation type"; +-- the post-type-checking type used by all the Core passes of GHC. +-- Unwraps only the outermost level; for example, the result might +-- be a NewTcApp; c.f. newTypeRep +predTypeRep (IParam _ ty) = ty +predTypeRep (ClassP clas tys) = mkTyConApp (classTyCon clas) tys + -- Result might be a NewTcApp, but the consumer will + -- look through that too if necessary \end{code} -\begin{code} -instantiateUsage - :: Ord3 u => [(u, GenType t u')] -> GenType t u -> GenType t u' -instantiateUsage = panic "instantiateUsage: not implemented" +%************************************************************************ +%* * + NewTypes +%* * +%************************************************************************ + +\begin{code} +splitRecNewType_maybe :: Type -> Maybe Type +-- Newtypes are always represented by a NewTcApp +-- Sometimes we want to look through a recursive newtype, and that's what happens here +-- It only strips *one layer* off, so the caller will usually call itself recursively +-- Only applied to types of kind *, hence the newtype is always saturated +splitRecNewType_maybe (NoteTy _ ty) = splitRecNewType_maybe ty +splitRecNewType_maybe (PredTy p) = splitRecNewType_maybe (predTypeRep p) +splitRecNewType_maybe (NewTcApp tc tys) + | isRecursiveTyCon tc + = ASSERT( tys `lengthIs` tyConArity tc && isNewTyCon tc ) + -- The assert should hold because splitRecNewType_maybe + -- should only be applied to *types* (of kind *) + Just (new_type_rhs tc tys) +splitRecNewType_maybe other = Nothing + +----------------------------- +newTypeRep :: TyCon -> [Type] -> Type +-- A local helper function (not exported) +-- Expands *the outermoset level of* a newtype application to +-- *either* a vanilla TyConApp (recursive newtype, or non-saturated) +-- *or* the newtype representation (otherwise), meaning the +-- type written in the RHS of the newtype decl, +-- which may itself be a newtype +-- +-- Example: newtype R = MkR S +-- newtype S = MkS T +-- newtype T = MkT (T -> T) +-- newTypeRep on R gives NewTcApp S +-- on S gives NewTcApp T +-- on T gives TyConApp T +-- +-- NB: the returned TyConApp is always deconstructed immediately by the +-- caller... a TyConApp with a newtype type constructor never lives +-- in an ordinary type +newTypeRep tc tys + | not (isRecursiveTyCon tc), -- Not recursive and saturated + tys `lengthIs` tyConArity tc -- treat as equivalent to expansion + = new_type_rhs tc tys + | otherwise + = TyConApp tc tys + -- ToDo: Consider caching this substitution in a NType + +-- new_type_rhs doesn't ask any questions: +-- it just expands newtype one level, whether recursive or not +new_type_rhs tc tys + = case newTyConRhs tc of + (tvs, rep_ty) -> substTyWith tvs tys rep_ty \end{code} -Expand abbreviations -~~~~~~~~~~~~~~~~~~~~ -Removes just the top level of any abbreviations. +%************************************************************************ +%* * +\subsection{Kinds and free variables} +%* * +%************************************************************************ + +--------------------------------------------------------------------- + Finding the kind of a type + ~~~~~~~~~~~~~~~~~~~~~~~~~~ \begin{code} -expandTy :: Type -> Type -- Restricted to Type due to Dict expansion +typeKind :: Type -> Kind + +typeKind (TyVarTy tyvar) = tyVarKind tyvar +typeKind (TyConApp tycon tys) = foldr (\_ k -> kindFunResult k) (tyConKind tycon) tys +typeKind (NewTcApp tycon tys) = foldr (\_ k -> kindFunResult k) (tyConKind tycon) tys +typeKind (NoteTy _ ty) = typeKind ty +typeKind (PredTy _) = liftedTypeKind -- Predicates are always + -- represented by lifted types +typeKind (AppTy fun arg) = kindFunResult (typeKind fun) +typeKind (FunTy arg res) = liftedTypeKind +typeKind (ForAllTy tv ty) = typeKind ty +\end{code} -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 - [] -> voidTy -- Empty dictionary represented by Void +--------------------------------------------------------------------- + Free variables of a type + ~~~~~~~~~~~~~~~~~~~~~~~~ +\begin{code} +tyVarsOfType :: Type -> TyVarSet +tyVarsOfType (TyVarTy tv) = unitVarSet tv +tyVarsOfType (TyConApp tycon tys) = tyVarsOfTypes tys +tyVarsOfType (NewTcApp tycon tys) = tyVarsOfTypes tys +tyVarsOfType (NoteTy (FTVNote tvs) ty2) = tvs +tyVarsOfType (NoteTy (SynNote ty1) ty2) = tyVarsOfType ty2 -- See note [Syn] below +tyVarsOfType (PredTy sty) = tyVarsOfPred 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 + +-- Note [Syn] +-- Consider +-- type T a = Int +-- What are the free tyvars of (T x)? Empty, of course! +-- Here's the example that Ralf Laemmel showed me: +-- foo :: (forall a. C u a -> C u a) -> u +-- mappend :: Monoid u => u -> u -> u +-- +-- bar :: Monoid u => u +-- bar = foo (\t -> t `mappend` t) +-- We have to generalise at the arg to f, and we don't +-- want to capture the constraint (Monad (C u a)) because +-- it appears to mention a. Pretty silly, but it was useful to him. - [arg_ty] -> expandTy arg_ty -- just the itself - -- 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! +tyVarsOfTypes :: [Type] -> TyVarSet +tyVarsOfTypes tys = foldr (unionVarSet.tyVarsOfType) emptyVarSet tys - other -> ASSERT(not (null all_arg_tys)) - foldl AppTy (TyConTy (tupleTyCon (length all_arg_tys)) u) all_arg_tys +tyVarsOfPred :: PredType -> TyVarSet +tyVarsOfPred (IParam _ ty) = tyVarsOfType ty +tyVarsOfPred (ClassP _ tys) = tyVarsOfTypes tys - -- 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). - where - all_arg_tys = classDictArgTys clas ty +tyVarsOfTheta :: ThetaType -> TyVarSet +tyVarsOfTheta = foldr (unionVarSet . tyVarsOfPred) emptyVarSet -expandTy ty = ty +-- 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} -At present there are no unboxed non-primitive types, so -isUnboxedType is the same as isPrimType. +%************************************************************************ +%* * +\subsection{TidyType} +%* * +%************************************************************************ + +tidyTy tidies up a type for printing in an error message, or in +an interface file. -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". +It doesn't change the uniques at all, just the print names. \begin{code} -isPrimType, isUnboxedType :: Type -> Bool +tidyTyVarBndr :: TidyEnv -> TyVar -> (TidyEnv, TyVar) +tidyTyVarBndr (tidy_env, subst) tyvar + = case tidyOccName tidy_env (getOccName name) of + (tidy', occ') -> ((tidy', subst'), tyvar') + where + subst' = extendVarEnv subst tyvar tyvar' + tyvar' = setTyVarName tyvar name' + name' = mkInternalName (getUnique name) occ' noSrcLoc + -- Note: make a *user* tyvar, so it printes nicely + -- Could extract src loc, but no need. + where + name = tyVarName tyvar + +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)) -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 +tidyOpenTyVars :: TidyEnv -> [TyVar] -> (TidyEnv, [TyVar]) +tidyOpenTyVars env tyvars = mapAccumL tidyOpenTyVar env tyvars -isPrimType _ = False +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 -isUnboxedType = isPrimType +tidyType :: TidyEnv -> Type -> Type +tidyType env@(tidy_env, subst) ty + = go ty + where + 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 (NewTcApp tycon tys) = let args = map go tys + in args `seqList` NewTcApp tycon args + go (NoteTy note ty) = (NoteTy $! (go_note note)) $! (go ty) + go (PredTy sty) = PredTy (tidyPred 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_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 -> PredType -> PredType +tidyPred env (IParam n ty) = IParam n (tidyType env ty) +tidyPred env (ClassP clas tys) = ClassP clas (tidyTypes env tys) \end{code} -This is *not* right: it is a placeholder (ToDo 96/03 WDP): + +@tidyOpenType@ grabs the free type variables, tidies them +and then uses @tidyType@ to work over the type itself + \begin{code} -typePrimRep :: Type -> PrimRep +tidyOpenType :: TidyEnv -> Type -> (TidyEnv, Type) +tidyOpenType env ty + = (env', tidyType env' ty) + where + env' = tidyFreeTyVars env (tyVarsOfType ty) + +tidyOpenTypes :: TidyEnv -> [Type] -> (TidyEnv, [Type]) +tidyOpenTypes env tys = mapAccumL tidyOpenType env tys -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, PtrRep) -- Not VoidRep! That's just for Void# - -- The type Void is represented by a pointer to - -- a bottom closure. - ,(wordPrimTyConKey, WordRep) - ] +tidyTopType :: Type -> Type +tidyTopType ty = tidyType emptyTidyEnv ty \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 (PredTy _) = False -- All source types are lifted +isUnLiftedType (NewTcApp tc tys) = isUnLiftedType (newTypeRep tc tys) +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( ty_args `lengthIs` tyConArity tc ) + isAlgTyCon tc + other -> False +\end{code} + +@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. -@matchTys@ matches corresponding elements of a list of templates and -types. +\begin{code} +isStrictType (ForAllTy tv ty) = isStrictType ty +isStrictType (NoteTy _ ty) = isStrictType ty +isStrictType (TyConApp tc _) = isUnLiftedTyCon tc +isStrictType (NewTcApp tc tys) = isStrictType (newTypeRep tc tys) +isStrictType (PredTy pred) = isStrictPred pred +isStrictType other = False + +isStrictPred (ClassP clas _) = opt_DictsStrict && not (isNewTyCon (classTyCon clas)) +isStrictPred other = False + -- 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.] +\end{code} \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 +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( ty_args `lengthIs` tyConArity tc ) + isPrimTyCon tc + other -> False \end{code} -@match@ is the main function. + +%************************************************************************ +%* * +\subsection{Sequencing on types +%* * +%************************************************************************ \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 +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 (PredTy p) = seqPred p +seqType (TyConApp tc tys) = tc `seq` seqTypes tys +seqType (NewTcApp tc tys) = tc `seq` seqTypes tys +seqType (ForAllTy tv ty) = tv `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 :: PredType -> () +seqPred (ClassP c tys) = c `seq` seqTypes tys +seqPred (IParam n ty) = n `seq` seqType ty \end{code} + %************************************************************************ %* * \subsection{Equality 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. +Comparison; don't use instances so that we know where it happens. +Look through newtypes but not usage types. -\begin{code} -eqSimpleTheta :: (Eq t,Eq u) => - [(Class,GenType t u)] -> [(Class,GenType t u)] -> Bool +Note that eqType can respond 'False' for partial applications of newtypes. +Consider + newtype Parser m a = MkParser (Foogle m a) -eqSimpleTheta [] [] = True -eqSimpleTheta ((c1,t1):th1) ((c2,t2):th2) = - c1==c2 && t1 `eqSimpleTy` t2 && th1 `eqSimpleTheta` th2 -eqSimpleTheta other1 other2 = False -\end{code} +Does + Monad (Parser m) `eqType` Monad (Foogle m) + +Well, yes, but eqType won't see that they are the same. +I don't think this is harmful, but it's soemthing to watch out for. \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} +eqType t1 t2 = eq_ty emptyVarEnv t1 t2 -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). +-- 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 -\begin{code} -eqTy :: Type -> Type -> Bool - -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 -\end{code} +-- Look through PredTy and NewTcApp. This is where the looping danger comes from. +-- We don't bother to check for the PredType/PredType case, no good reason +-- Hmm: maybe there is a good reason: see the notes below about newtypes +eq_ty env (PredTy sty1) t2 = eq_ty env (predTypeRep sty1) t2 +eq_ty env t1 (PredTy sty2) = eq_ty env t1 (predTypeRep sty2) -\begin{code} -showTypeCategory :: Type -> Char - {- - {C,I,F,D} char, int, float, double - T tuple - S other single-constructor type - {c,i,f,d} unboxed ditto - t *unpacked* tuple - s *unpacked" single-cons... - - v void# - a primitive array - - E enumeration type - + dictionary, unless it's a ... - L List - > function - M other (multi-constructor) data-con type - . other type - - reserved for others to mark as "uninteresting" - -} -showTypeCategory ty - = if isDictTy ty - then '+' - else - case getTyCon_maybe ty of - Nothing -> if maybeToBool (getFunTy_maybe ty) - then '>' - else '.' - - Just tycon -> - let utc = uniqueOf tycon in - if utc == charDataConKey then 'C' - else if utc == intDataConKey then 'I' - else if utc == floatDataConKey then 'F' - else if utc == doubleDataConKey then 'D' - else if utc == integerDataConKey then 'J' - else if utc == charPrimTyConKey then 'c' - else if (utc == intPrimTyConKey || utc == wordPrimTyConKey - || utc == addrPrimTyConKey) then 'i' - else if utc == floatPrimTyConKey then 'f' - else if utc == doublePrimTyConKey then 'd' - else if isPrimTyCon tycon {- array, we hope -} then 'A' - else if isEnumerationTyCon tycon then 'E' - else if isTupleTyCon tycon then 'T' - else if maybeToBool (maybeTyConSingleCon tycon) then 'S' - else if utc == listTyConKey then 'L' - else 'M' -- oh, well... +-- NB: we *cannot* short-cut the newtype comparison thus: +-- eq_ty env (NewTcApp tc1 tys1) (NewTcApp tc2 tys2) +-- | (tc1 == tc2) = (eq_tys env tys1 tys2) +-- +-- Consider: +-- newtype T a = MkT [a] +-- newtype Foo m = MkFoo (forall a. m a -> Int) +-- w1 :: Foo [] +-- w1 = ... +-- +-- w2 :: Foo T +-- w2 = MkFoo (\(MkT x) -> case w1 of MkFoo f -> f x) +-- +-- We end up with w2 = w1; so we need that Foo T = Foo [] +-- but we can only expand saturated newtypes, so just comparing +-- T with [] won't do. + +eq_ty env (NewTcApp tc1 tys1) t2 = eq_ty env (newTypeRep tc1 tys1) t2 +eq_ty env t1 (NewTcApp tc2 tys2) = eq_ty env t1 (newTypeRep tc2 tys2) + +-- 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 (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} +