X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fiface%2FIfaceSyn.lhs;h=44ce2359fedbb07009d4b5bdcaf6b725050f40f3;hp=7957050f631b2503a6eeeabaaadb452050f8f585;hb=6a05ec5ef5373f61b7f9f5bdc344483417fa801b;hpb=7653e16d0afab8e25eb5015aa4d0c1d03d6ab4a3 diff --git a/compiler/iface/IfaceSyn.lhs b/compiler/iface/IfaceSyn.lhs index 7957050..44ce235 100644 --- a/compiler/iface/IfaceSyn.lhs +++ b/compiler/iface/IfaceSyn.lhs @@ -1,36 +1,33 @@ % +% (c) The University of Glasgow 2006 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998 % -%************************************************************************ -%* * -\section[HsCore]{Core-syntax unfoldings in Haskell interface files} -%* * -%************************************************************************ - -We could either use this, or parameterise @GenCoreExpr@ on @Types@ and -@TyVars@ as well. Currently trying the former... MEGA SIGH. \begin{code} +{-# OPTIONS -w #-} +-- The above warning supression flag is a temporary kludge. +-- While working on this module you are encouraged to remove it and fix +-- any warnings in the module. See +-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings +-- for details + module IfaceSyn ( module IfaceType, -- Re-export all this IfaceDecl(..), IfaceClassOp(..), IfaceConDecl(..), IfaceConDecls(..), - IfaceExpr(..), IfaceAlt, IfaceNote(..), + IfaceExpr(..), IfaceAlt, IfaceNote(..), IfaceLetBndr(..), IfaceBinding(..), IfaceConAlt(..), IfaceIdInfo(..), - IfaceInfoItem(..), IfaceRule(..), IfaceInst(..), + IfaceInfoItem(..), IfaceRule(..), IfaceInst(..), IfaceFamInst(..), -- Misc - visibleIfConDecls, - - -- Converting things to IfaceSyn - tyThingToIfaceDecl, instanceToIfaceInst, coreRuleToIfaceRule, + ifaceDeclSubBndrs, visibleIfConDecls, -- Equality - IfaceEq(..), (&&&), bool, eqListBy, eqMaybeBy, - eqIfDecl, eqIfInst, eqIfRule, + GenIfaceEq(..), IfaceEq, (&&&), bool, eqListBy, eqMaybeBy, + eqIfDecl, eqIfInst, eqIfFamInst, eqIfRule, checkBootDecl, -- Pretty printing - pprIfaceExpr, pprIfaceDecl, pprIfaceDeclHead + pprIfaceExpr, pprIfaceDeclHead ) where #include "HsVersions.h" @@ -38,39 +35,21 @@ module IfaceSyn ( import CoreSyn import IfaceType -import FunDeps ( pprFundeps ) -import NewDemand ( StrictSig, pprIfaceStrictSig ) -import TcType ( deNoteType ) -import Type ( TyThing(..), splitForAllTys, funResultTy ) -import InstEnv ( Instance(..), OverlapFlag ) -import Id ( Id, idName, idType, idInfo, idArity, isDataConWorkId_maybe, isFCallId_maybe ) -import NewDemand ( isTopSig ) -import IdInfo ( IdInfo, CafInfo(..), WorkerInfo(..), - arityInfo, cafInfo, newStrictnessInfo, - workerInfo, unfoldingInfo, inlinePragInfo ) -import TyCon ( TyCon, ArgVrcs, AlgTyConRhs(..), isRecursiveTyCon, isForeignTyCon, - isSynTyCon, isAlgTyCon, isPrimTyCon, isFunTyCon, - isTupleTyCon, tupleTyConBoxity, tyConStupidTheta, - tyConHasGenerics, tyConArgVrcs, synTyConRhs, - tyConArity, tyConTyVars, algTyConRhs, tyConExtName ) -import DataCon ( dataConName, dataConSig, dataConFieldLabels, dataConStrictMarks, - dataConTyCon, dataConIsInfix, isVanillaDataCon ) -import Class ( FunDep, DefMeth, classExtraBigSig, classTyCon ) -import OccName ( OccName, OccEnv, emptyOccEnv, - lookupOccEnv, extendOccEnv, parenSymOcc, - OccSet, unionOccSets, unitOccSet ) -import Name ( Name, NamedThing(..), nameOccName, isExternalName ) -import CostCentre ( CostCentre, pprCostCentreCore ) -import Literal ( Literal ) -import ForeignCall ( ForeignCall ) -import TysPrim ( alphaTyVars ) -import BasicTypes ( Arity, Activation(..), StrictnessMark, - RecFlag(..), boolToRecFlag, Boxity(..), - tupleParens ) +import NewDemand +import Class +import UniqFM +import NameSet +import Name +import CostCentre +import Literal +import ForeignCall +import BasicTypes import Outputable import FastString -import Maybes ( catMaybes ) -import Util ( lengthIs ) +import Module + +import Data.List +import Data.Maybe infixl 3 &&& infix 4 `eqIfExt`, `eqIfIdInfo`, `eqIfType` @@ -89,33 +68,51 @@ data IfaceDecl ifType :: IfaceType, ifIdInfo :: IfaceIdInfo } - | IfaceData { ifName :: OccName, -- Type constructor - ifTyVars :: [IfaceTvBndr], -- Type variables - ifCtxt :: IfaceContext, -- The "stupid theta" - ifCons :: IfaceConDecls, -- Includes new/data info - ifRec :: RecFlag, -- Recursive or not? - ifVrcs :: ArgVrcs, - ifGeneric :: Bool -- True <=> generic converter functions available - } -- We need this for imported data decls, since the - -- imported modules may have been compiled with - -- different flags to the current compilation unit - - | IfaceSyn { ifName :: OccName, -- Type constructor - ifTyVars :: [IfaceTvBndr], -- Type variables - ifVrcs :: ArgVrcs, - ifSynRhs :: IfaceType -- synonym expansion + | IfaceData { ifName :: OccName, -- Type constructor + ifTyVars :: [IfaceTvBndr], -- Type variables + ifCtxt :: IfaceContext, -- The "stupid theta" + ifCons :: IfaceConDecls, -- Includes new/data info + ifRec :: RecFlag, -- Recursive or not? + ifGadtSyntax :: Bool, -- True <=> declared using + -- GADT syntax + ifGeneric :: Bool, -- True <=> generic converter + -- functions available + -- We need this for imported + -- data decls, since the + -- imported modules may have + -- been compiled with + -- different flags to the + -- current compilation unit + ifFamInst :: Maybe (IfaceTyCon, [IfaceType]) + -- Just <=> instance of family + -- Invariant: + -- ifCons /= IfOpenDataTyCon + -- for family instances + } + + | IfaceSyn { ifName :: OccName, -- Type constructor + ifTyVars :: [IfaceTvBndr], -- Type variables + ifOpenSyn :: Bool, -- Is an open family? + ifSynRhs :: IfaceType, -- Type for an ordinary + -- synonym and kind for an + -- open family + ifFamInst :: Maybe (IfaceTyCon, [IfaceType]) + -- Just <=> instance of family + -- Invariant: ifOpenSyn == False + -- for family instances } | IfaceClass { ifCtxt :: IfaceContext, -- Context... ifName :: OccName, -- Name of the class ifTyVars :: [IfaceTvBndr], -- Type variables - ifFDs :: [FunDep OccName], -- Functional dependencies + ifFDs :: [FunDep FastString], -- Functional dependencies + ifATs :: [IfaceDecl], -- Associated type families ifSigs :: [IfaceClassOp], -- Method signatures - ifRec :: RecFlag, -- Is newtype/datatype associated with the class recursive? - ifVrcs :: ArgVrcs -- ... and what are its argument variances ... + ifRec :: RecFlag -- Is newtype/datatype associated with the class recursive? } - | IfaceForeign { ifName :: OccName, -- Needs expanding when we move beyond .NET + | IfaceForeign { ifName :: OccName, -- Needs expanding when we move + -- beyond .NET ifExtName :: Maybe FastString } data IfaceClassOp = IfaceClassOp OccName DefMeth IfaceType @@ -125,35 +122,35 @@ data IfaceClassOp = IfaceClassOp OccName DefMeth IfaceType data IfaceConDecls = IfAbstractTyCon -- No info + | IfOpenDataTyCon -- Open data family | IfDataTyCon [IfaceConDecl] -- data type decls | IfNewTyCon IfaceConDecl -- newtype decls visibleIfConDecls :: IfaceConDecls -> [IfaceConDecl] visibleIfConDecls IfAbstractTyCon = [] +visibleIfConDecls IfOpenDataTyCon = [] visibleIfConDecls (IfDataTyCon cs) = cs visibleIfConDecls (IfNewTyCon c) = [c] data IfaceConDecl - = IfVanillaCon { - ifConOcc :: OccName, -- Constructor name + = IfCon { + ifConOcc :: OccName, -- Constructor name ifConInfix :: Bool, -- True <=> declared infix - ifConArgTys :: [IfaceType], -- Arg types - ifConStricts :: [StrictnessMark], -- Empty (meaning all lazy), or 1-1 corresp with arg types - ifConFields :: [OccName] } -- ...ditto... (field labels) - | IfGadtCon { - ifConOcc :: OccName, -- Constructor name - ifConTyVars :: [IfaceTvBndr], -- All tyvars + ifConUnivTvs :: [IfaceTvBndr], -- Universal tyvars + ifConExTvs :: [IfaceTvBndr], -- Existential tyvars + ifConEqSpec :: [(OccName,IfaceType)], -- Equality contraints ifConCtxt :: IfaceContext, -- Non-stupid context ifConArgTys :: [IfaceType], -- Arg types - ifConResTys :: [IfaceType], -- Result type args - ifConStricts :: [StrictnessMark] } -- Empty (meaning all lazy), or 1-1 corresp with arg types - + ifConFields :: [OccName], -- ...ditto... (field labels) + ifConStricts :: [StrictnessMark]} -- Empty (meaning all lazy), + -- or 1-1 corresp with arg tys + data IfaceInst - = IfaceInst { ifInstCls :: IfaceExtName, -- See comments with + = IfaceInst { ifInstCls :: Name, -- See comments with ifInstTys :: [Maybe IfaceTyCon], -- the defn of Instance - ifDFun :: OccName, -- The dfun + ifDFun :: Name, -- The dfun ifOFlag :: OverlapFlag, -- Overlap flag - ifInstOrph :: Maybe OccName } -- See is_orph in defn of Instance + ifInstOrph :: Maybe OccName } -- See Note [Orphans] -- There's always a separate IfaceDecl for the DFun, which gives -- its IdInfo with its full type and version number. -- The instance declarations taken together have a version number, @@ -161,12 +158,18 @@ data IfaceInst -- If this instance decl is *used*, we'll record a usage on the dfun; -- and if the head does not change it won't be used if it wasn't before +data IfaceFamInst + = IfaceFamInst { ifFamInstFam :: Name -- Family tycon + , ifFamInstTys :: [Maybe IfaceTyCon] -- Rough match types + , ifFamInstTyCon :: IfaceTyCon -- Instance decl + } + data IfaceRule = IfaceRule { ifRuleName :: RuleName, ifActivation :: Activation, ifRuleBndrs :: [IfaceBndr], -- Tyvars and term vars - ifRuleHead :: IfaceExtName, -- Head of lhs + ifRuleHead :: Name, -- Head of lhs ifRuleArgs :: [IfaceExpr], -- Args of LHS ifRuleRhs :: IfaceExpr, ifRuleOrph :: Maybe OccName -- Just like IfaceInst @@ -189,9 +192,10 @@ data IfaceIdInfo data IfaceInfoItem = HsArity Arity | HsStrictness StrictSig - | HsUnfold Activation IfaceExpr + | HsInline Activation + | HsUnfold IfaceExpr | HsNoCafRefs - | HsWorker IfaceExtName Arity -- Worker, if any see IdInfo.WorkerInfo + | HsWorker Name Arity -- Worker, if any see IdInfo.WorkerInfo -- for why we want arity here. -- NB: we need IfaceExtName (not just OccName) because the worker -- can simplify to a function in another module. @@ -200,49 +204,222 @@ data IfaceInfoItem -------------------------------- data IfaceExpr - = IfaceLcl OccName - | IfaceExt IfaceExtName + = IfaceLcl FastString + | IfaceExt Name | IfaceType IfaceType | IfaceTuple Boxity [IfaceExpr] -- Saturated; type arguments omitted | IfaceLam IfaceBndr IfaceExpr | IfaceApp IfaceExpr IfaceExpr - | IfaceCase IfaceExpr OccName IfaceType [IfaceAlt] + | IfaceCase IfaceExpr FastString IfaceType [IfaceAlt] | IfaceLet IfaceBinding IfaceExpr | IfaceNote IfaceNote IfaceExpr + | IfaceCast IfaceExpr IfaceCoercion | IfaceLit Literal | IfaceFCall ForeignCall IfaceType + | IfaceTick Module Int data IfaceNote = IfaceSCC CostCentre - | IfaceCoerce IfaceType - | IfaceInlineCall | IfaceInlineMe | IfaceCoreNote String -type IfaceAlt = (IfaceConAlt, [OccName], IfaceExpr) - -- Note: OccName, not IfaceBndr (and same with the case binder) +type IfaceAlt = (IfaceConAlt, [FastString], IfaceExpr) + -- Note: FastString, not IfaceBndr (and same with the case binder) -- We reconstruct the kind/type of the thing from the context -- thus saving bulk in interface files data IfaceConAlt = IfaceDefault - | IfaceDataAlt OccName + | IfaceDataAlt Name | IfaceTupleAlt Boxity | IfaceLitAlt Literal data IfaceBinding - = IfaceNonRec IfaceIdBndr IfaceExpr - | IfaceRec [(IfaceIdBndr, IfaceExpr)] + = IfaceNonRec IfaceLetBndr IfaceExpr + | IfaceRec [(IfaceLetBndr, IfaceExpr)] + +-- IfaceLetBndr is like IfaceIdBndr, but has IdInfo too +-- It's used for *non-top-level* let/rec binders +-- See Note [IdInfo on nested let-bindings] +data IfaceLetBndr = IfLetBndr FastString IfaceType IfaceIdInfo \end{code} +Note [IdInfo on nested let-bindings] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Occasionally we want to preserve IdInfo on nested let bindings The one +that came up was a NOINLINE pragma on a let-binding inside an INLINE +function. The user (Duncan Coutts) really wanted the NOINLINE control +to cross the separate compilation boundary. -%************************************************************************ -%* * -\subsection[HsCore-print]{Printing Core unfoldings} -%* * -%************************************************************************ +So a IfaceLetBndr keeps a trimmed-down list of IfaceIdInfo stuff. +Currently we only actually retain InlinePragInfo, but in principle we could +add strictness etc. + + +Note [Orphans]: the ifInstOrph and ifRuleOrph fields +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If a module contains any "orphans", then its interface file is read +regardless, so that its instances are not missed. + +Roughly speaking, an instance is an orphan if its head (after the =>) +mentions nothing defined in this module. Functional dependencies +complicate the situation though. Consider + + module M where { class C a b | a -> b } + +and suppose we are compiling module X: + + module X where + import M + data T = ... + instance C Int T where ... + +This instance is an orphan, because when compiling a third module Y we +might get a constraint (C Int v), and we'd want to improve v to T. So +we must make sure X's instances are loaded, even if we do not directly +use anything from X. + +More precisely, an instance is an orphan iff + + If there are no fundeps, then at least of the names in + the instance head is locally defined. + + If there are fundeps, then for every fundep, at least one of the + names free in a *non-determined* part of the instance head is + defined in this module. + +(Note that these conditions hold trivially if the class is locally +defined.) + +Note [Versioning of instances] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Now consider versioning. If we *use* an instance decl in one compilation, +we'll depend on the dfun id for that instance, so we'll recompile if it changes. +But suppose we *don't* (currently) use an instance! We must recompile if +the instance is changed in such a way that it becomes important. (This would +only matter with overlapping instances, else the importing module wouldn't have +compiled before and the recompilation check is irrelevant.) + +The is_orph field is set to (Just n) if the instance is not an orphan. +The 'n' is *any* of the locally-defined names mentioned anywhere in the +instance head. This name is used for versioning; the instance decl is +considered part of the defn of this 'n'. + +I'm worried about whether this works right if we pick a name from +a functionally-dependent part of the instance decl. E.g. + + module M where { class C a b | a -> b } + +and suppose we are compiling module X: + + module X where + import M + data S = ... + data T = ... + instance C S T where ... + +If we base the instance verion on T, I'm worried that changing S to S' +would change T's version, but not S or S'. But an importing module might +not depend on T, and so might not be recompiled even though the new instance +(C S' T) might be relevant. I have not been able to make a concrete example, +and it seems deeply obscure, so I'm going to leave it for now. + + +Note [Versioning of rules] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +A rule that is not an orphan has an ifRuleOrph field of (Just n), where +n appears on the LHS of the rule; any change in the rule changes the version of n. ------------------------------ Printing IfaceDecl ------------------------------------ \begin{code} +-- ----------------------------------------------------------------------------- +-- Utils on IfaceSyn + +ifaceDeclSubBndrs :: IfaceDecl -> [OccName] +-- *Excludes* the 'main' name, but *includes* the implicitly-bound names +-- Deeply revolting, because it has to predict what gets bound, +-- especially the question of whether there's a wrapper for a datacon + +-- N.B. the set of names returned here *must* match the set of +-- TyThings returned by HscTypes.implicitTyThings, in the sense that +-- TyThing.getOccName should define a bijection between the two lists. +-- This invariant is used in LoadIface.loadDecl (see note [Tricky iface loop]) +-- The order of the list does not matter. +ifaceDeclSubBndrs IfaceData {ifCons = IfAbstractTyCon} = [] + +-- Newtype +ifaceDeclSubBndrs (IfaceData {ifName = tc_occ, + ifCons = IfNewTyCon ( + IfCon { ifConOcc = con_occ, + ifConFields = fields + }), + ifFamInst = famInst}) + = -- fields (names of selectors) + fields ++ + -- implicit coerion and (possibly) family instance coercion + (mkNewTyCoOcc tc_occ) : (famInstCo famInst tc_occ) ++ + -- data constructor and worker (newtypes don't have a wrapper) + [con_occ, mkDataConWorkerOcc con_occ] + + +ifaceDeclSubBndrs (IfaceData {ifName = tc_occ, + ifCons = IfDataTyCon cons, + ifFamInst = famInst}) + = -- fields (names of selectors) + nub (concatMap ifConFields cons) -- Eliminate duplicate fields + -- (possibly) family instance coercion; + -- there is no implicit coercion for non-newtypes + ++ famInstCo famInst tc_occ + -- for each data constructor in order, + -- data constructor, worker, and (possibly) wrapper + ++ concatMap dc_occs cons + where + dc_occs con_decl + | has_wrapper = [con_occ, work_occ, wrap_occ] + | otherwise = [con_occ, work_occ] + where + con_occ = ifConOcc con_decl -- DataCon namespace + wrap_occ = mkDataConWrapperOcc con_occ -- Id namespace + work_occ = mkDataConWorkerOcc con_occ -- Id namespace + strs = ifConStricts con_decl + has_wrapper = any isMarkedStrict strs -- See MkId.mkDataConIds (sigh) + || not (null . ifConEqSpec $ con_decl) + || isJust famInst + -- ToDo: may miss strictness in existential dicts + +ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ, + ifSigs = sigs, ifATs = ats }) + = -- dictionary datatype: + -- type constructor + tc_occ : + -- (possibly) newtype coercion + co_occs ++ + -- data constructor (DataCon namespace) + -- data worker (Id namespace) + -- no wrapper (class dictionaries never have a wrapper) + [dc_occ, dcww_occ] ++ + -- associated types + [ifName at | at <- ats ] ++ + -- superclass selectors + [mkSuperDictSelOcc n cls_occ | n <- [1..n_ctxt]] ++ + -- operation selectors + [op | IfaceClassOp op _ _ <- sigs] + where + n_ctxt = length sc_ctxt + n_sigs = length sigs + tc_occ = mkClassTyConOcc cls_occ + dc_occ = mkClassDataConOcc cls_occ + co_occs | is_newtype = [mkNewTyCoOcc tc_occ] + | otherwise = [] + dcww_occ = mkDataConWorkerOcc dc_occ + is_newtype = n_sigs + n_ctxt == 1 -- Sigh + +ifaceDeclSubBndrs _other = [] + +-- coercion for data/newtype family instances +famInstCo Nothing baseOcc = [] +famInstCo (Just _) baseOcc = [mkInstTyCoOcc baseOcc] + +----------------------------- Printing IfaceDecl ------------------------------ + instance Outputable IfaceDecl where ppr = pprIfaceDecl @@ -253,69 +430,85 @@ pprIfaceDecl (IfaceId {ifName = var, ifType = ty, ifIdInfo = info}) pprIfaceDecl (IfaceForeign {ifName = tycon}) = hsep [ptext SLIT("foreign import type dotnet"), ppr tycon] -pprIfaceDecl (IfaceSyn {ifName = tycon, ifTyVars = tyvars, ifSynRhs = mono_ty, ifVrcs = vrcs}) +pprIfaceDecl (IfaceSyn {ifName = tycon, ifTyVars = tyvars, + ifOpenSyn = False, ifSynRhs = mono_ty, + ifFamInst = mbFamInst}) = hang (ptext SLIT("type") <+> pprIfaceDeclHead [] tycon tyvars) - 4 (vcat [equals <+> ppr mono_ty, - pprVrcs vrcs]) + 4 (vcat [equals <+> ppr mono_ty, pprFamily mbFamInst]) + +pprIfaceDecl (IfaceSyn {ifName = tycon, ifTyVars = tyvars, + ifOpenSyn = True, ifSynRhs = mono_ty}) + = hang (ptext SLIT("type family") <+> pprIfaceDeclHead [] tycon tyvars) + 4 (dcolon <+> ppr mono_ty) pprIfaceDecl (IfaceData {ifName = tycon, ifGeneric = gen, ifCtxt = context, ifTyVars = tyvars, ifCons = condecls, - ifRec = isrec, ifVrcs = vrcs}) + ifRec = isrec, ifFamInst = mbFamInst}) = hang (pp_nd <+> pprIfaceDeclHead context tycon tyvars) - 4 (vcat [pprVrcs vrcs, pprRec isrec, pprGen gen, pp_condecls tycon condecls]) + 4 (vcat [pprRec isrec, pprGen gen, pp_condecls tycon condecls, + pprFamily mbFamInst]) where pp_nd = case condecls of IfAbstractTyCon -> ptext SLIT("data") + IfOpenDataTyCon -> ptext SLIT("data family") IfDataTyCon _ -> ptext SLIT("data") IfNewTyCon _ -> ptext SLIT("newtype") pprIfaceDecl (IfaceClass {ifCtxt = context, ifName = clas, ifTyVars = tyvars, - ifFDs = fds, ifSigs = sigs, ifVrcs = vrcs, ifRec = isrec}) + ifFDs = fds, ifATs = ats, ifSigs = sigs, + ifRec = isrec}) = hang (ptext SLIT("class") <+> pprIfaceDeclHead context clas tyvars <+> pprFundeps fds) - 4 (vcat [pprVrcs vrcs, - pprRec isrec, - sep (map ppr sigs)]) + 4 (vcat [pprRec isrec, + sep (map ppr ats), + sep (map ppr sigs)]) -pprVrcs vrcs = ptext SLIT("Variances") <+> ppr vrcs pprRec isrec = ptext SLIT("RecFlag") <+> ppr isrec pprGen True = ptext SLIT("Generics: yes") pprGen False = ptext SLIT("Generics: no") +pprFamily Nothing = ptext SLIT("FamilyInstance: none") +pprFamily (Just famInst) = ptext SLIT("FamilyInstance:") <+> ppr famInst + instance Outputable IfaceClassOp where ppr (IfaceClassOp n dm ty) = ppr n <+> ppr dm <+> dcolon <+> ppr ty pprIfaceDeclHead :: IfaceContext -> OccName -> [IfaceTvBndr] -> SDoc -pprIfaceDeclHead context thing tyvars - = hsep [pprIfaceContext context, parenSymOcc thing (ppr thing), pprIfaceTvBndrs tyvars] +pprIfaceDeclHead context thing tyvars + = hsep [pprIfaceContext context, parenSymOcc thing (ppr thing), + pprIfaceTvBndrs tyvars] pp_condecls tc IfAbstractTyCon = ptext SLIT("{- abstract -}") pp_condecls tc (IfNewTyCon c) = equals <+> pprIfaceConDecl tc c +pp_condecls tc IfOpenDataTyCon = empty pp_condecls tc (IfDataTyCon cs) = equals <+> sep (punctuate (ptext SLIT(" |")) - (map (pprIfaceConDecl tc) cs)) - -pprIfaceConDecl tc (IfVanillaCon { - ifConOcc = name, ifConInfix = is_infix, - ifConArgTys = arg_tys, - ifConStricts = strs, ifConFields = fields }) - = sep [ppr name <+> sep (map pprParendIfaceType arg_tys), - if is_infix then ptext SLIT("Infix") else empty, - if null strs then empty + (map (pprIfaceConDecl tc) cs)) + +pprIfaceConDecl :: OccName -> IfaceConDecl -> SDoc +pprIfaceConDecl tc + (IfCon { ifConOcc = name, ifConInfix = is_infix, + ifConUnivTvs = univ_tvs, ifConExTvs = ex_tvs, + ifConEqSpec = eq_spec, ifConCtxt = ctxt, ifConArgTys = arg_tys, + ifConStricts = strs, ifConFields = fields }) + = sep [main_payload, + if is_infix then ptext SLIT("Infix") else empty, + if null strs then empty else nest 4 (ptext SLIT("Stricts:") <+> hsep (map ppr strs)), - if null fields then empty + if null fields then empty else nest 4 (ptext SLIT("Fields:") <+> hsep (map ppr fields))] + where + main_payload = ppr name <+> dcolon <+> + pprIfaceForAllPart (univ_tvs ++ ex_tvs) (eq_ctxt ++ ctxt) pp_tau -pprIfaceConDecl tc (IfGadtCon { - ifConOcc = name, - ifConTyVars = tvs, ifConCtxt = ctxt, - ifConArgTys = arg_tys, ifConResTys = res_tys, - ifConStricts = strs }) - = sep [ppr name <+> dcolon <+> pprIfaceForAllPart tvs ctxt (ppr con_tau), - if null strs then empty - else nest 4 (ptext SLIT("Stricts:") <+> hsep (map ppr strs))] - where - con_tau = foldr1 IfaceFunTy (arg_tys ++ [tc_app]) - tc_app = IfaceTyConApp (IfaceTc (LocalTop tc)) res_tys - -- Gruesome, but jsut for debug print + eq_ctxt = [(IfaceEqPred (IfaceTyVar (occNameFS tv)) ty) + | (tv,ty) <- eq_spec] + + -- A bit gruesome this, but we can't form the full con_tau, and ppr it, + -- because we don't have a Name for the tycon, only an OccName + pp_tau = case map pprParendIfaceType arg_tys ++ [pp_res_ty] of + (t:ts) -> fsep (t : map (arrow <+>) ts) + [] -> panic "pp_con_taus" + + pp_res_ty = ppr tc <+> fsep [ppr tv | (tv,_) <- univ_tvs] instance Outputable IfaceRule where ppr (IfaceRule { ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs, @@ -330,11 +523,19 @@ instance Outputable IfaceInst where ppr (IfaceInst {ifDFun = dfun_id, ifOFlag = flag, ifInstCls = cls, ifInstTys = mb_tcs}) = hang (ptext SLIT("instance") <+> ppr flag - <+> ppr cls <+> brackets (pprWithCommas ppr_mb mb_tcs)) + <+> ppr cls <+> brackets (pprWithCommas ppr_rough mb_tcs)) 2 (equals <+> ppr dfun_id) - where - ppr_mb Nothing = dot - ppr_mb (Just tc) = ppr tc + +instance Outputable IfaceFamInst where + ppr (IfaceFamInst {ifFamInstFam = fam, ifFamInstTys = mb_tcs, + ifFamInstTyCon = tycon_id}) + = hang (ptext SLIT("family instance") <+> + ppr fam <+> brackets (pprWithCommas ppr_rough mb_tcs)) + 2 (equals <+> ppr tycon_id) + +ppr_rough :: Maybe IfaceTyCon -> SDoc +ppr_rough Nothing = dot +ppr_rough (Just tc) = ppr tc \end{code} @@ -352,6 +553,7 @@ pprIfaceExpr add_par (IfaceLcl v) = ppr v pprIfaceExpr add_par (IfaceExt v) = ppr v pprIfaceExpr add_par (IfaceLit l) = ppr l pprIfaceExpr add_par (IfaceFCall cc ty) = braces (ppr cc <+> ppr ty) +pprIfaceExpr add_par (IfaceTick m ix) = braces (text "tick" <+> ppr m <+> ppr ix) pprIfaceExpr add_par (IfaceType ty) = char '@' <+> pprParendIfaceType ty pprIfaceExpr add_par app@(IfaceApp _ _) = add_par (pprIfaceApp app []) @@ -365,20 +567,23 @@ pprIfaceExpr add_par e@(IfaceLam _ _) collect bs (IfaceLam b e) = collect (b:bs) e collect bs e = (reverse bs, e) --- gaw 2004 pprIfaceExpr add_par (IfaceCase scrut bndr ty [(con, bs, rhs)]) --- gaw 2004 - = add_par (sep [ptext SLIT("case") <+> char '@' <+> pprParendIfaceType ty <+> pprIfaceExpr noParens scrut <+> ptext SLIT("of") + = add_par (sep [ptext SLIT("case") <+> char '@' <+> pprParendIfaceType ty + <+> pprIfaceExpr noParens scrut <+> ptext SLIT("of") <+> ppr bndr <+> char '{' <+> ppr_con_bs con bs <+> arrow, pprIfaceExpr noParens rhs <+> char '}']) --- gaw 2004 pprIfaceExpr add_par (IfaceCase scrut bndr ty alts) --- gaw 2004 - = add_par (sep [ptext SLIT("case") <+> char '@' <+> pprParendIfaceType ty <+> pprIfaceExpr noParens scrut <+> ptext SLIT("of") + = add_par (sep [ptext SLIT("case") <+> char '@' <+> pprParendIfaceType ty + <+> pprIfaceExpr noParens scrut <+> ptext SLIT("of") <+> ppr bndr <+> char '{', nest 2 (sep (map ppr_alt alts)) <+> char '}']) +pprIfaceExpr add_par (IfaceCast expr co) + = sep [pprIfaceExpr parens expr, + nest 2 (ptext SLIT("`cast`")), + pprParendIfaceType co] + pprIfaceExpr add_par (IfaceLet (IfaceNonRec b rhs) body) = add_par (sep [ptext SLIT("let {"), nest 2 (ppr_bind (b, rhs)), @@ -399,8 +604,9 @@ ppr_alt (con, bs, rhs) = sep [ppr_con_bs con bs, ppr_con_bs (IfaceTupleAlt tup_con) bs = tupleParens tup_con (interpp'SP bs) ppr_con_bs con bs = ppr con <+> hsep (map ppr bs) -ppr_bind ((b,ty),rhs) = sep [ppr b <+> dcolon <+> ppr ty, - equals <+> pprIfaceExpr noParens rhs] +ppr_bind (IfLetBndr b ty info, rhs) + = sep [hang (ppr b <+> dcolon <+> ppr ty) 2 (ppr info), + equals <+> pprIfaceExpr noParens rhs] ------------------ pprIfaceApp (IfaceApp fun arg) args = pprIfaceApp fun (nest 2 (pprIfaceExpr parens arg) : args) @@ -409,11 +615,10 @@ pprIfaceApp fun args = sep (pprIfaceExpr parens fun : args) ------------------ instance Outputable IfaceNote where ppr (IfaceSCC cc) = pprCostCentreCore cc - ppr (IfaceCoerce ty) = ptext SLIT("__coerce") <+> pprParendIfaceType ty - ppr IfaceInlineCall = ptext SLIT("__inline_call") ppr IfaceInlineMe = ptext SLIT("__inline_me") ppr (IfaceCoreNote s) = ptext SLIT("__core_note") <+> pprHsString (mkFastString s) + instance Outputable IfaceConAlt where ppr IfaceDefault = text "DEFAULT" ppr (IfaceLitAlt l) = ppr l @@ -423,281 +628,17 @@ instance Outputable IfaceConAlt where ------------------ instance Outputable IfaceIdInfo where - ppr NoInfo = empty - ppr (HasInfo is) = ptext SLIT("{-") <+> fsep (map ppr_hs_info is) <+> ptext SLIT("-}") - -ppr_hs_info (HsUnfold prag unf) = sep [ptext SLIT("Unfolding: ") <> ppr prag, - parens (pprIfaceExpr noParens unf)] -ppr_hs_info (HsArity arity) = ptext SLIT("Arity:") <+> int arity -ppr_hs_info (HsStrictness str) = ptext SLIT("Strictness:") <+> pprIfaceStrictSig str -ppr_hs_info HsNoCafRefs = ptext SLIT("HasNoCafRefs") -ppr_hs_info (HsWorker w a) = ptext SLIT("Worker:") <+> ppr w <+> int a -\end{code} - - -%************************************************************************ -%* * - Converting things to their Iface equivalents -%* * -%************************************************************************ - - -\begin{code} -tyThingToIfaceDecl :: (Name -> IfaceExtName) -> TyThing -> IfaceDecl --- Assumption: the thing is already tidied, so that locally-bound names --- (lambdas, for-alls) already have non-clashing OccNames --- Reason: Iface stuff uses OccNames, and the conversion here does --- not do tidying on the way -tyThingToIfaceDecl ext (AnId id) - = IfaceId { ifName = getOccName id, - ifType = toIfaceType ext (idType id), - ifIdInfo = info } - where - info = case toIfaceIdInfo ext (idInfo id) of - [] -> NoInfo - items -> HasInfo items - -tyThingToIfaceDecl ext (AClass clas) - = IfaceClass { ifCtxt = toIfaceContext ext sc_theta, - ifName = getOccName clas, - ifTyVars = toIfaceTvBndrs clas_tyvars, - ifFDs = map toIfaceFD clas_fds, - ifSigs = map toIfaceClassOp op_stuff, - ifRec = boolToRecFlag (isRecursiveTyCon tycon), - ifVrcs = tyConArgVrcs tycon } - where - (clas_tyvars, clas_fds, sc_theta, _, op_stuff) = classExtraBigSig clas - tycon = classTyCon clas - - toIfaceClassOp (sel_id, def_meth) - = ASSERT(sel_tyvars == clas_tyvars) - IfaceClassOp (getOccName sel_id) def_meth (toIfaceType ext op_ty) - where - -- Be careful when splitting the type, because of things - -- like class Foo a where - -- op :: (?x :: String) => a -> a - -- and class Baz a where - -- op :: (Ord a) => a -> a - (sel_tyvars, rho_ty) = splitForAllTys (idType sel_id) - op_ty = funResultTy rho_ty - - toIfaceFD (tvs1, tvs2) = (map getOccName tvs1, map getOccName tvs2) - -tyThingToIfaceDecl ext (ATyCon tycon) - | isSynTyCon tycon - = IfaceSyn { ifName = getOccName tycon, - ifTyVars = toIfaceTvBndrs tyvars, - ifVrcs = tyConArgVrcs tycon, - ifSynRhs = toIfaceType ext syn_ty } - - | isAlgTyCon tycon - = IfaceData { ifName = getOccName tycon, - ifTyVars = toIfaceTvBndrs tyvars, - ifCtxt = toIfaceContext ext (tyConStupidTheta tycon), - ifCons = ifaceConDecls (algTyConRhs tycon), - ifRec = boolToRecFlag (isRecursiveTyCon tycon), - ifVrcs = tyConArgVrcs tycon, - ifGeneric = tyConHasGenerics tycon } - - | isForeignTyCon tycon - = IfaceForeign { ifName = getOccName tycon, - ifExtName = tyConExtName tycon } - - | isPrimTyCon tycon || isFunTyCon tycon - -- Needed in GHCi for ':info Int#', for example - = IfaceData { ifName = getOccName tycon, - ifTyVars = toIfaceTvBndrs (take (tyConArity tycon) alphaTyVars), - ifCtxt = [], - ifCons = IfAbstractTyCon, - ifGeneric = False, - ifRec = NonRecursive, - ifVrcs = tyConArgVrcs tycon } - - | otherwise = pprPanic "toIfaceDecl" (ppr tycon) - where - tyvars = tyConTyVars tycon - syn_ty = synTyConRhs tycon - - ifaceConDecls (NewTyCon { data_con = con }) = IfNewTyCon (ifaceConDecl con) - ifaceConDecls (DataTyCon { data_cons = cons }) = IfDataTyCon (map ifaceConDecl cons) - ifaceConDecls AbstractTyCon = IfAbstractTyCon - -- The last case happens when a TyCon has been trimmed during tidying - -- Furthermore, tyThingToIfaceDecl is also used - -- in TcRnDriver for GHCi, when browsing a module, in which case the - -- AbstractTyCon case is perfectly sensible. - - ifaceConDecl data_con - | isVanillaDataCon data_con - = IfVanillaCon {ifConOcc = getOccName (dataConName data_con), - ifConInfix = dataConIsInfix data_con, - ifConArgTys = map (toIfaceType ext) arg_tys, - ifConStricts = strict_marks, - ifConFields = map getOccName field_labels } - | otherwise - = IfGadtCon { ifConOcc = getOccName (dataConName data_con), - ifConTyVars = toIfaceTvBndrs tyvars, - ifConCtxt = toIfaceContext ext theta, - ifConArgTys = map (toIfaceType ext) arg_tys, - ifConResTys = map (toIfaceType ext) res_tys, - ifConStricts = strict_marks } - where - (tyvars, theta, arg_tys, _, res_tys) = dataConSig data_con - field_labels = dataConFieldLabels data_con - strict_marks = dataConStrictMarks data_con - -tyThingToIfaceDecl ext (ADataCon dc) - = pprPanic "toIfaceDecl" (ppr dc) -- Should be trimmed out earlier - - --------------------------- -instanceToIfaceInst :: (Name -> IfaceExtName) -> Instance -> IfaceInst -instanceToIfaceInst ext_lhs ispec@(Instance { is_dfun = dfun_id, is_flag = oflag, - is_cls = cls, is_tcs = mb_tcs, - is_orph = orph }) - = IfaceInst { ifDFun = getOccName dfun_id, - ifOFlag = oflag, - ifInstCls = ext_lhs cls, - ifInstTys = map do_rough mb_tcs, - ifInstOrph = orph } - where - do_rough Nothing = Nothing - do_rough (Just n) = Just (toIfaceTyCon_name ext_lhs n) - --------------------------- -toIfaceIdInfo :: (Name -> IfaceExtName) -> IdInfo -> [IfaceInfoItem] -toIfaceIdInfo ext id_info - = catMaybes [arity_hsinfo, caf_hsinfo, strict_hsinfo, - wrkr_hsinfo, unfold_hsinfo] - where - ------------ Arity -------------- - arity_info = arityInfo id_info - arity_hsinfo | arity_info == 0 = Nothing - | otherwise = Just (HsArity arity_info) - - ------------ Caf Info -------------- - caf_info = cafInfo id_info - caf_hsinfo = case caf_info of - NoCafRefs -> Just HsNoCafRefs - _other -> Nothing - - ------------ Strictness -------------- - -- No point in explicitly exporting TopSig - strict_hsinfo = case newStrictnessInfo id_info of - Just sig | not (isTopSig sig) -> Just (HsStrictness sig) - _other -> Nothing - - ------------ Worker -------------- - work_info = workerInfo id_info - has_worker = case work_info of { HasWorker _ _ -> True; other -> False } - wrkr_hsinfo = case work_info of - HasWorker work_id wrap_arity -> - Just (HsWorker (ext (idName work_id)) wrap_arity) - NoWorker -> Nothing - - ------------ Unfolding -------------- - -- The unfolding is redundant if there is a worker - unfold_info = unfoldingInfo id_info - inline_prag = inlinePragInfo id_info - rhs = unfoldingTemplate unfold_info - unfold_hsinfo | neverUnfold unfold_info -- The CoreTidy phase retains unfolding info iff - || has_worker = Nothing -- we want to expose the unfolding, taking into account - -- unconditional NOINLINE, etc. See TidyPgm.addExternal - | otherwise = Just (HsUnfold inline_prag (toIfaceExpr ext rhs)) - --------------------------- -coreRuleToIfaceRule :: (Name -> IfaceExtName) -- For the LHS names - -> (Name -> IfaceExtName) -- For the RHS names - -> CoreRule -> IfaceRule -coreRuleToIfaceRule ext_lhs ext_rhs (BuiltinRule { ru_fn = fn}) - = pprTrace "toHsRule: builtin" (ppr fn) $ - bogusIfaceRule (mkIfaceExtName fn) - -coreRuleToIfaceRule ext_lhs ext_rhs - (Rule { ru_name = name, ru_fn = fn, ru_act = act, ru_bndrs = bndrs, - ru_args = args, ru_rhs = rhs, ru_orph = orph }) - = IfaceRule { ifRuleName = name, ifActivation = act, - ifRuleBndrs = map (toIfaceBndr ext_lhs) bndrs, - ifRuleHead = ext_lhs fn, - ifRuleArgs = map do_arg args, - ifRuleRhs = toIfaceExpr ext_rhs rhs, - ifRuleOrph = orph } - where - -- For type args we must remove synonyms from the outermost - -- level. Reason: so that when we read it back in we'll - -- construct the same ru_rough field as we have right now; - -- see tcIfaceRule - do_arg (Type ty) = IfaceType (toIfaceType ext_lhs (deNoteType ty)) - do_arg arg = toIfaceExpr ext_lhs arg - -bogusIfaceRule :: IfaceExtName -> IfaceRule -bogusIfaceRule id_name - = IfaceRule { ifRuleName = FSLIT("bogus"), ifActivation = NeverActive, - ifRuleBndrs = [], ifRuleHead = id_name, ifRuleArgs = [], - ifRuleRhs = IfaceExt id_name, ifRuleOrph = Nothing } - ---------------------- -toIfaceExpr :: (Name -> IfaceExtName) -> CoreExpr -> IfaceExpr -toIfaceExpr ext (Var v) = toIfaceVar ext v -toIfaceExpr ext (Lit l) = IfaceLit l -toIfaceExpr ext (Type ty) = IfaceType (toIfaceType ext ty) -toIfaceExpr ext (Lam x b) = IfaceLam (toIfaceBndr ext x) (toIfaceExpr ext b) -toIfaceExpr ext (App f a) = toIfaceApp ext f [a] --- gaw 2004 -toIfaceExpr ext (Case s x ty as) = IfaceCase (toIfaceExpr ext s) (getOccName x) (toIfaceType ext ty) (map (toIfaceAlt ext) as) -toIfaceExpr ext (Let b e) = IfaceLet (toIfaceBind ext b) (toIfaceExpr ext e) -toIfaceExpr ext (Note n e) = IfaceNote (toIfaceNote ext n) (toIfaceExpr ext e) - ---------------------- -toIfaceNote ext (SCC cc) = IfaceSCC cc -toIfaceNote ext (Coerce t1 _) = IfaceCoerce (toIfaceType ext t1) -toIfaceNote ext InlineCall = IfaceInlineCall -toIfaceNote ext InlineMe = IfaceInlineMe -toIfaceNote ext (CoreNote s) = IfaceCoreNote s - ---------------------- -toIfaceBind ext (NonRec b r) = IfaceNonRec (toIfaceIdBndr ext b) (toIfaceExpr ext r) -toIfaceBind ext (Rec prs) = IfaceRec [(toIfaceIdBndr ext b, toIfaceExpr ext r) | (b,r) <- prs] - ---------------------- -toIfaceAlt ext (c,bs,r) = (toIfaceCon c, map getOccName bs, toIfaceExpr ext r) - ---------------------- -toIfaceCon (DataAlt dc) | isTupleTyCon tc = IfaceTupleAlt (tupleTyConBoxity tc) - | otherwise = IfaceDataAlt (getOccName dc) - where - tc = dataConTyCon dc - -toIfaceCon (LitAlt l) = IfaceLitAlt l -toIfaceCon DEFAULT = IfaceDefault - ---------------------- -toIfaceApp ext (App f a) as = toIfaceApp ext f (a:as) -toIfaceApp ext (Var v) as - = case isDataConWorkId_maybe v of - -- We convert the *worker* for tuples into IfaceTuples - Just dc | isTupleTyCon tc && saturated - -> IfaceTuple (tupleTyConBoxity tc) tup_args - where - val_args = dropWhile isTypeArg as - saturated = val_args `lengthIs` idArity v - tup_args = map (toIfaceExpr ext) val_args - tc = dataConTyCon dc - - other -> mkIfaceApps ext (toIfaceVar ext v) as - -toIfaceApp ext e as = mkIfaceApps ext (toIfaceExpr ext e) as - -mkIfaceApps ext f as = foldl (\f a -> IfaceApp f (toIfaceExpr ext a)) f as - ---------------------- -toIfaceVar :: (Name -> IfaceExtName) -> Id -> IfaceExpr -toIfaceVar ext v - | Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType ext (idType v)) - -- Foreign calls have special syntax - | isExternalName name = IfaceExt (ext name) - | otherwise = IfaceLcl (nameOccName name) - where - name = idName v + ppr NoInfo = empty + ppr (HasInfo is) = ptext SLIT("{-") <+> fsep (map ppr is) <+> ptext SLIT("-}") + +instance Outputable IfaceInfoItem where + ppr (HsUnfold unf) = ptext SLIT("Unfolding:") <+> + parens (pprIfaceExpr noParens unf) + ppr (HsInline act) = ptext SLIT("Inline:") <+> ppr act + ppr (HsArity arity) = ptext SLIT("Arity:") <+> int arity + ppr (HsStrictness str) = ptext SLIT("Strictness:") <+> pprIfaceStrictSig str + ppr HsNoCafRefs = ptext SLIT("HasNoCafRefs") + ppr (HsWorker w a) = ptext SLIT("Worker:") <+> ppr w <+> int a \end{code} @@ -707,23 +648,35 @@ toIfaceVar ext v %* * %************************************************************************ -Equality over IfaceSyn returns an IfaceEq, not a Bool. The new constructor is -EqBut, which gives the set of *locally-defined* things whose version must be equal -for the whole thing to be equal. So the key function is eqIfExt, which compares -IfaceExtNames. +Equality over IfaceSyn returns an IfaceEq, not a Bool. The new +constructor is EqBut, which gives the set of things whose version must +be equal for the whole thing to be equal. So the key function is +eqIfExt, which compares Names. Of course, equality is also done modulo alpha conversion. \begin{code} -data IfaceEq +data GenIfaceEq a = Equal -- Definitely exactly the same | NotEqual -- Definitely different - | EqBut OccSet -- The same provided these local things have not changed + | EqBut a -- The same provided these Names have not changed + +type IfaceEq = GenIfaceEq NameSet + +instance Outputable IfaceEq where + ppr Equal = ptext SLIT("Equal") + ppr NotEqual = ptext SLIT("NotEqual") + ppr (EqBut occset) = ptext SLIT("EqBut") <+> ppr (nameSetToList occset) bool :: Bool -> IfaceEq bool True = Equal bool False = NotEqual +toBool :: IfaceEq -> Bool +toBool Equal = True +toBool (EqBut _) = True +toBool NotEqual = False + zapEq :: IfaceEq -> IfaceEq -- Used to forget EqBut information zapEq (EqBut _) = Equal zapEq other = other @@ -731,23 +684,55 @@ zapEq other = other (&&&) :: IfaceEq -> IfaceEq -> IfaceEq Equal &&& x = x NotEqual &&& x = NotEqual -EqBut occs &&& Equal = EqBut occs -EqBut occs &&& NotEqual = NotEqual -EqBut occs1 &&& EqBut occs2 = EqBut (occs1 `unionOccSets` occs2) +EqBut nms &&& Equal = EqBut nms +EqBut nms &&& NotEqual = NotEqual +EqBut nms1 &&& EqBut nms2 = EqBut (nms1 `unionNameSets` nms2) ---------------------- -eqIfExt :: IfaceExtName -> IfaceExtName -> IfaceEq -- This function is the core of the EqBut stuff -eqIfExt (ExtPkg mod1 occ1) (ExtPkg mod2 occ2) = bool (mod1==mod2 && occ1==occ2) -eqIfExt (HomePkg mod1 occ1 v1) (HomePkg mod2 occ2 v2) = bool (mod1==mod2 && occ1==occ2 && v1==v2) -eqIfExt (LocalTop occ1) (LocalTop occ2) | occ1 == occ2 = EqBut (unitOccSet occ1) -eqIfExt (LocalTopSub occ1 p1) (LocalTop occ2) | occ1 == occ2 = EqBut (unitOccSet p1) -eqIfExt (LocalTopSub occ1 p1) (LocalTopSub occ2 _) | occ1 == occ2 = EqBut (unitOccSet p1) -eqIfExt n1 n2 = NotEqual -\end{code} +-- ASSUMPTION: The left-hand argument is the NEW CODE, and hence +-- any Names in the left-hand arg have the correct parent in them. +eqIfExt :: Name -> Name -> IfaceEq +eqIfExt name1 name2 + | name1 == name2 = EqBut (unitNameSet name1) + | otherwise = NotEqual +--------------------- +checkBootDecl :: IfaceDecl -- The boot decl + -> IfaceDecl -- The real decl + -> Bool -- True <=> compatible +checkBootDecl (IfaceId s1 t1 _) (IfaceId s2 t2 _) + = ASSERT( s1==s2 ) toBool (t1 `eqIfType` t2) + +checkBootDecl d1@(IfaceForeign {}) d2@(IfaceForeign {}) + = ASSERT (ifName d1 == ifName d2 ) ifExtName d1 == ifExtName d2 + +checkBootDecl d1@(IfaceSyn {}) d2@(IfaceSyn {}) + = ASSERT( ifName d1 == ifName d2 ) + toBool $ eqWith (ifTyVars d1) (ifTyVars d2) $ \ env -> + eq_ifType env (ifSynRhs d1) (ifSynRhs d2) + +checkBootDecl d1@(IfaceData {}) d2@(IfaceData {}) +-- We don't check the recursion flags because the boot-one is +-- recursive, to be conservative, but the real one may not be. +-- I'm not happy with the way recursive flags are dealt with. + = ASSERT( ifName d1 == ifName d2 ) + toBool $ eqWith (ifTyVars d1) (ifTyVars d2) $ \ env -> + eq_ifContext env (ifCtxt d1) (ifCtxt d2) &&& + case ifCons d1 of + IfAbstractTyCon -> Equal + cons1 -> eq_hsCD env cons1 (ifCons d2) + +checkBootDecl d1@(IfaceClass {}) d2@(IfaceClass {}) + = ASSERT( ifName d1 == ifName d2 ) + toBool $ eqWith (ifTyVars d1) (ifTyVars d2) $ \ env -> + eqListBy (eq_hsFD env) (ifFDs d1) (ifFDs d2) &&& + case (ifCtxt d1, ifSigs d1) of + ([], []) -> Equal + (cxt1, sigs1) -> eq_ifContext env cxt1 (ifCtxt d2) &&& + eqListBy (eq_cls_sig env) sigs1 (ifSigs d2) + +checkBootDecl _ _ = False -- default case -\begin{code} --------------------- eqIfDecl :: IfaceDecl -> IfaceDecl -> IfaceEq eqIfDecl (IfaceId s1 t1 i1) (IfaceId s2 t2 i2) @@ -759,8 +744,9 @@ eqIfDecl d1@(IfaceForeign {}) d2@(IfaceForeign {}) eqIfDecl d1@(IfaceData {}) d2@(IfaceData {}) = bool (ifName d1 == ifName d2 && ifRec d1 == ifRec d2 && - ifVrcs d1 == ifVrcs d2 && + ifGadtSyntax d1 == ifGadtSyntax d2 && ifGeneric d1 == ifGeneric d2) &&& + ifFamInst d1 `eqIfTc_fam` ifFamInst d2 &&& eqWith (ifTyVars d1) (ifTyVars d2) (\ env -> eq_ifContext env (ifCtxt d1) (ifCtxt d2) &&& eq_hsCD env (ifCons d1) (ifCons d2) @@ -771,17 +757,18 @@ eqIfDecl d1@(IfaceData {}) d2@(IfaceData {}) eqIfDecl d1@(IfaceSyn {}) d2@(IfaceSyn {}) = bool (ifName d1 == ifName d2) &&& + ifFamInst d1 `eqIfTc_fam` ifFamInst d2 &&& eqWith (ifTyVars d1) (ifTyVars d2) (\ env -> eq_ifType env (ifSynRhs d1) (ifSynRhs d2) ) eqIfDecl d1@(IfaceClass {}) d2@(IfaceClass {}) = bool (ifName d1 == ifName d2 && - ifRec d1 == ifRec d2 && - ifVrcs d1 == ifVrcs d2) &&& + ifRec d1 == ifRec d2) &&& eqWith (ifTyVars d1) (ifTyVars d2) (\ env -> eq_ifContext env (ifCtxt d1) (ifCtxt d2) &&& eqListBy (eq_hsFD env) (ifFDs d1) (ifFDs d2) &&& + eqListBy eqIfDecl (ifATs d1) (ifATs d2) &&& eqListBy (eq_cls_sig env) (ifSigs d1) (ifSigs d2) ) @@ -791,10 +778,22 @@ eqIfDecl _ _ = NotEqual -- default case eqWith :: [IfaceTvBndr] -> [IfaceTvBndr] -> (EqEnv -> IfaceEq) -> IfaceEq eqWith = eq_ifTvBndrs emptyEqEnv +eqIfTc_fam :: Maybe (IfaceTyCon, [IfaceType]) + -> Maybe (IfaceTyCon, [IfaceType]) + -> IfaceEq +Nothing `eqIfTc_fam` Nothing = Equal +(Just (fam1, tys1)) `eqIfTc_fam` (Just (fam2, tys2)) = + fam1 `eqIfTc` fam2 &&& eqListBy eqIfType tys1 tys2 +_ `eqIfTc_fam` _ = NotEqual + + ----------------------- -eqIfInst d1 d2 = bool (ifDFun d1 == ifDFun d2) +eqIfInst d1 d2 = bool (ifDFun d1 == ifDFun d2 && ifOFlag d1 == ifOFlag d2) -- All other changes are handled via the version info on the dfun +eqIfFamInst d1 d2 = bool (ifFamInstTyCon d1 == ifFamInstTyCon d2) +-- All other changes are handled via the version info on the tycon + eqIfRule (IfaceRule n1 a1 bs1 f1 es1 rhs1 o1) (IfaceRule n2 a2 bs2 f2 es2 rhs2 o2) = bool (n1==n2 && a1==a2 && o1 == o2) &&& @@ -809,24 +808,18 @@ eq_hsCD env (IfDataTyCon c1) (IfDataTyCon c2) eq_hsCD env (IfNewTyCon c1) (IfNewTyCon c2) = eq_ConDecl env c1 c2 eq_hsCD env IfAbstractTyCon IfAbstractTyCon = Equal +eq_hsCD env IfOpenDataTyCon IfOpenDataTyCon = Equal eq_hsCD env d1 d2 = NotEqual -eq_ConDecl env c1@(IfVanillaCon {}) c2@(IfVanillaCon {}) +eq_ConDecl env c1 c2 = bool (ifConOcc c1 == ifConOcc c2 && ifConInfix c1 == ifConInfix c2 && ifConStricts c1 == ifConStricts c2 && ifConFields c1 == ifConFields c2) &&& - eq_ifTypes env (ifConArgTys c1) (ifConArgTys c2) - -eq_ConDecl env c1@(IfGadtCon {}) c2@(IfGadtCon {}) - = bool (ifConOcc c1 == ifConOcc c2 && - ifConStricts c1 == ifConStricts c2) &&& - eq_ifTvBndrs env (ifConTyVars c1) (ifConTyVars c2) (\ env -> + eq_ifTvBndrs env (ifConUnivTvs c1) (ifConUnivTvs c2) (\ env -> + eq_ifTvBndrs env (ifConExTvs c1) (ifConExTvs c2) (\ env -> eq_ifContext env (ifConCtxt c1) (ifConCtxt c2) &&& - eq_ifTypes env (ifConResTys c1) (ifConResTys c2) &&& - eq_ifTypes env (ifConArgTys c1) (ifConArgTys c2)) - -eq_ConDecl env c1 c2 = NotEqual + eq_ifTypes env (ifConArgTys c1) (ifConArgTys c2))) eq_hsFD env (ns1,ms1) (ns2,ms2) = eqListBy (eqIfOcc env) ns1 ns2 &&& eqListBy (eqIfOcc env) ms1 ms2 @@ -840,11 +833,12 @@ eq_cls_sig env (IfaceClassOp n1 dm1 ty1) (IfaceClassOp n2 dm2 ty2) ----------------- eqIfIdInfo NoInfo NoInfo = Equal eqIfIdInfo (HasInfo is1) (HasInfo is2) = eqListBy eq_item is1 is2 -eqIfIdInfo i1 i2 = NotEqual +eqIfIdInfo i1 i2 = NotEqual +eq_item (HsInline a1) (HsInline a2) = bool (a1 == a2) eq_item (HsArity a1) (HsArity a2) = bool (a1 == a2) eq_item (HsStrictness s1) (HsStrictness s2) = bool (s1 == s2) -eq_item (HsUnfold a1 u1) (HsUnfold a2 u2) = bool (a1 == a2) &&& eq_ifaceExpr emptyEqEnv u1 u2 +eq_item (HsUnfold u1) (HsUnfold u2) = eq_ifaceExpr emptyEqEnv u1 u2 eq_item HsNoCafRefs HsNoCafRefs = Equal eq_item (HsWorker wkr1 a1) (HsWorker wkr2 a2) = bool (a1==a2) &&& (wkr1 `eqIfExt` wkr2) eq_item _ _ = NotEqual @@ -855,10 +849,12 @@ eq_ifaceExpr env (IfaceLcl v1) (IfaceLcl v2) = eqIfOcc env v1 v2 eq_ifaceExpr env (IfaceExt v1) (IfaceExt v2) = eqIfExt v1 v2 eq_ifaceExpr env (IfaceLit l1) (IfaceLit l2) = bool (l1 == l2) eq_ifaceExpr env (IfaceFCall c1 ty1) (IfaceFCall c2 ty2) = bool (c1==c2) &&& eq_ifType env ty1 ty2 +eq_ifaceExpr env (IfaceTick m1 ix1) (IfaceTick m2 ix2) = bool (m1==m2) &&& bool (ix1 == ix2) eq_ifaceExpr env (IfaceType ty1) (IfaceType ty2) = eq_ifType env ty1 ty2 eq_ifaceExpr env (IfaceTuple n1 as1) (IfaceTuple n2 as2) = bool (n1==n2) &&& eqListBy (eq_ifaceExpr env) as1 as2 eq_ifaceExpr env (IfaceLam b1 body1) (IfaceLam b2 body2) = eq_ifBndr env b1 b2 (\env -> eq_ifaceExpr env body1 body2) eq_ifaceExpr env (IfaceApp f1 a1) (IfaceApp f2 a2) = eq_ifaceExpr env f1 f2 &&& eq_ifaceExpr env a1 a2 +eq_ifaceExpr env (IfaceCast e1 co1) (IfaceCast e2 co2) = eq_ifaceExpr env e1 e2 &&& eq_ifType env co1 co2 eq_ifaceExpr env (IfaceNote n1 r1) (IfaceNote n2 r2) = eq_ifaceNote env n1 n2 &&& eq_ifaceExpr env r1 r2 eq_ifaceExpr env (IfaceCase s1 b1 ty1 as1) (IfaceCase s2 b2 ty2 as2) @@ -871,10 +867,10 @@ eq_ifaceExpr env (IfaceCase s1 b1 ty1 as1) (IfaceCase s2 b2 ty2 as2) eq_ifNakedBndrs env bs1 bs2 (\env -> eq_ifaceExpr env r1 r2) eq_ifaceExpr env (IfaceLet (IfaceNonRec b1 r1) x1) (IfaceLet (IfaceNonRec b2 r2) x2) - = eq_ifaceExpr env r1 r2 &&& eq_ifIdBndr env b1 b2 (\env -> eq_ifaceExpr env x1 x2) + = eq_ifaceExpr env r1 r2 &&& eq_ifLetBndr env b1 b2 (\env -> eq_ifaceExpr env x1 x2) eq_ifaceExpr env (IfaceLet (IfaceRec as1) x1) (IfaceLet (IfaceRec as2) x2) - = eq_ifIdBndrs env bs1 bs2 (\env -> eqListBy (eq_ifaceExpr env) rs1 rs2 &&& eq_ifaceExpr env x1 x2) + = eq_ifLetBndrs env bs1 bs2 (\env -> eqListBy (eq_ifaceExpr env) rs1 rs2 &&& eq_ifaceExpr env x1 x2) where (bs1,rs1) = unzip as1 (bs2,rs2) = unzip as2 @@ -893,8 +889,6 @@ eq_ifaceConAlt _ _ = False ----------------- eq_ifaceNote :: EqEnv -> IfaceNote -> IfaceNote -> IfaceEq eq_ifaceNote env (IfaceSCC c1) (IfaceSCC c2) = bool (c1==c2) -eq_ifaceNote env (IfaceCoerce t1) (IfaceCoerce t2) = eq_ifType env t1 t2 -eq_ifaceNote env IfaceInlineCall IfaceInlineCall = Equal eq_ifaceNote env IfaceInlineMe IfaceInlineMe = Equal eq_ifaceNote env (IfaceCoreNote s1) (IfaceCoreNote s2) = bool (s1==s2) eq_ifaceNote env _ _ = NotEqual @@ -932,7 +926,12 @@ eqIfTc IfaceBoolTc IfaceBoolTc = Equal eqIfTc IfaceListTc IfaceListTc = Equal eqIfTc IfacePArrTc IfacePArrTc = Equal eqIfTc (IfaceTupTc bx1 ar1) (IfaceTupTc bx2 ar2) = bool (bx1==bx2 && ar1==ar2) -eqIfTc _ _ = NotEqual +eqIfTc IfaceLiftedTypeKindTc IfaceLiftedTypeKindTc = Equal +eqIfTc IfaceOpenTypeKindTc IfaceOpenTypeKindTc = Equal +eqIfTc IfaceUnliftedTypeKindTc IfaceUnliftedTypeKindTc = Equal +eqIfTc IfaceUbxTupleKindTc IfaceUbxTupleKindTc = Equal +eqIfTc IfaceArgTypeKindTc IfaceArgTypeKindTc = Equal +eqIfTc _ _ = NotEqual \end{code} ----------------------------------------------------------- @@ -941,24 +940,24 @@ eqIfTc _ _ = NotEqual \begin{code} ------------------------------------ -type EqEnv = OccEnv OccName -- Tracks the mapping from L-variables to R-variables +type EqEnv = UniqFM FastString -- Tracks the mapping from L-variables to R-variables -eqIfOcc :: EqEnv -> OccName -> OccName -> IfaceEq -eqIfOcc env n1 n2 = case lookupOccEnv env n1 of +eqIfOcc :: EqEnv -> FastString -> FastString -> IfaceEq +eqIfOcc env n1 n2 = case lookupUFM env n1 of Just n1 -> bool (n1 == n2) Nothing -> bool (n1 == n2) -extendEqEnv :: EqEnv -> OccName -> OccName -> EqEnv +extendEqEnv :: EqEnv -> FastString -> FastString -> EqEnv extendEqEnv env n1 n2 | n1 == n2 = env - | otherwise = extendOccEnv env n1 n2 + | otherwise = addToUFM env n1 n2 emptyEqEnv :: EqEnv -emptyEqEnv = emptyOccEnv +emptyEqEnv = emptyUFM ------------------------------------ type ExtEnv bndr = EqEnv -> bndr -> bndr -> (EqEnv -> IfaceEq) -> IfaceEq -eq_ifNakedBndr :: ExtEnv OccName +eq_ifNakedBndr :: ExtEnv FastString eq_ifBndr :: ExtEnv IfaceBndr eq_ifTvBndr :: ExtEnv IfaceTvBndr eq_ifIdBndr :: ExtEnv IfaceIdBndr @@ -969,17 +968,20 @@ eq_ifBndr env (IfaceIdBndr b1) (IfaceIdBndr b2) k = eq_ifIdBndr env b1 b2 k eq_ifBndr env (IfaceTvBndr b1) (IfaceTvBndr b2) k = eq_ifTvBndr env b1 b2 k eq_ifBndr _ _ _ _ = NotEqual -eq_ifTvBndr env (v1, k1) (v2, k2) k = bool (k1 == k2) &&& k (extendEqEnv env v1 v2) +eq_ifTvBndr env (v1, k1) (v2, k2) k = eq_ifType env k1 k2 &&& k (extendEqEnv env v1 v2) eq_ifIdBndr env (v1, t1) (v2, t2) k = eq_ifType env t1 t2 &&& k (extendEqEnv env v1 v2) +eq_ifLetBndr env (IfLetBndr v1 t1 i1) (IfLetBndr v2 t2 i2) k + = eq_ifType env t1 t2 &&& eqIfIdInfo i1 i2 &&& k (extendEqEnv env v1 v2) + eq_ifBndrs :: ExtEnv [IfaceBndr] -eq_ifIdBndrs :: ExtEnv [IfaceIdBndr] +eq_ifLetBndrs :: ExtEnv [IfaceLetBndr] eq_ifTvBndrs :: ExtEnv [IfaceTvBndr] -eq_ifNakedBndrs :: ExtEnv [OccName] +eq_ifNakedBndrs :: ExtEnv [FastString] eq_ifBndrs = eq_bndrs_with eq_ifBndr -eq_ifIdBndrs = eq_bndrs_with eq_ifIdBndr eq_ifTvBndrs = eq_bndrs_with eq_ifTvBndr eq_ifNakedBndrs = eq_bndrs_with eq_ifNakedBndr +eq_ifLetBndrs = eq_bndrs_with eq_ifLetBndr eq_bndrs_with eq env [] [] k = k env eq_bndrs_with eq env (b1:bs1) (b2:bs2) k = eq env b1 b2 (\env -> eq_bndrs_with eq env bs1 bs2 k)