diff options
Diffstat (limited to 'compiler/iface')
-rw-r--r-- | compiler/iface/BinIface.hs | 251 | ||||
-rw-r--r-- | compiler/iface/IfaceEnv.lhs | 160 | ||||
-rw-r--r-- | compiler/iface/IfaceSyn.lhs | 159 | ||||
-rw-r--r-- | compiler/iface/IfaceType.lhs | 141 | ||||
-rw-r--r-- | compiler/iface/LoadIface.lhs | 103 | ||||
-rw-r--r-- | compiler/iface/MkIface.lhs | 558 | ||||
-rw-r--r-- | compiler/iface/TcIface.lhs | 78 |
7 files changed, 763 insertions, 687 deletions
diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs index 3e9895a5bf..3e79a3947c 100644 --- a/compiler/iface/BinIface.hs +++ b/compiler/iface/BinIface.hs @@ -9,20 +9,39 @@ module BinIface ( writeBinIface, readBinIface, v_IgnoreHiWay ) where #include "HsVersions.h" +import TcRnMonad ( TcRnIf, ioToIOEnv ) +import IfaceEnv import HscTypes import BasicTypes import NewDemand import IfaceSyn +import Module ( ModuleName, mkModule, modulePackageId, moduleName ) +import Name +import OccName ( OccName ) import VarEnv import InstEnv ( OverlapFlag(..) ) import Class ( DefMeth(..) ) +import DynFlags ( DynFlags ) +import UniqFM ( UniqFM, eltsUFM ) +import UniqSupply ( uniqFromSupply, splitUniqSupply ) import CostCentre import StaticFlags ( opt_HiVersion, v_Build_tag ) +import Type ( Kind, + isLiftedTypeKind, isUnliftedTypeKind, isOpenTypeKind, + isArgTypeKind, isUbxTupleKind, liftedTypeKind, + unliftedTypeKind, openTypeKind, argTypeKind, + ubxTupleKind, mkArrowKind, splitFunTy_maybe ) +import PackageConfig ( PackageId ) import Panic import Binary +import SrcLoc ( noSrcLoc ) import Util +import ErrUtils ( debugTraceMsg ) import Config ( cGhcUnregisterised ) +import FastMutInt ( readFastMutInt ) +import Data.Word ( Word32 ) +import Data.Array ( Array, array, elems, listArray, (!) ) import DATA_IOREF import EXCEPTION ( throwDyn ) import Monad ( when ) @@ -31,19 +50,164 @@ import Outputable #include "HsVersions.h" -- --------------------------------------------------------------------------- -writeBinIface :: FilePath -> ModIface -> IO () -writeBinIface hi_path mod_iface - = putBinFileWithDict hi_path mod_iface - -readBinIface :: FilePath -> IO ModIface -readBinIface hi_path = getBinFileWithDict hi_path - - --- %********************************************************* --- %* * --- All the Binary instances --- %* * --- %********************************************************* +-- Reading and writing binary interface files + +readBinIface :: FilePath -> TcRnIf a b ModIface +readBinIface hi_path = do + nc <- getNameCache + (new_nc, iface) <- ioToIOEnv $ readBinIface_ hi_path nc + setNameCache new_nc + return iface + +readBinIface_ :: FilePath -> NameCache -> IO (NameCache, ModIface) +readBinIface_ hi_path nc = do + bh <- Binary.readBinMem hi_path + + -- Read the magic number to check that this really is a GHC .hi file + -- (This magic number does not change when we change + -- GHC interface file format) + magic <- get bh + when (magic /= binaryInterfaceMagic) $ + throwDyn (ProgramError ( + "magic number mismatch: old/corrupt interface file?")) + + -- Read the dictionary + -- The next word in the file is a pointer to where the dictionary is + -- (probably at the end of the file) + dict_p <- Binary.get bh -- Get the dictionary ptr + data_p <- tellBin bh -- Remember where we are now + seekBin bh dict_p + dict <- getDictionary bh + seekBin bh data_p -- Back to where we were before + + -- Initialise the user-data field of bh + ud <- newReadState dict + bh <- return (setUserData bh ud) + + symtab_p <- Binary.get bh -- Get the symtab ptr + data_p <- tellBin bh -- Remember where we are now + seekBin bh symtab_p + (nc', symtab) <- getSymbolTable bh nc + seekBin bh data_p -- Back to where we were before + let ud = getUserData bh + bh <- return $! setUserData bh ud{ud_symtab = symtab} + iface <- get bh + return (nc', iface) + + +writeBinIface :: DynFlags -> FilePath -> ModIface -> IO () +writeBinIface dflags hi_path mod_iface = do + bh <- openBinMem initBinMemSize + put_ bh binaryInterfaceMagic + + -- Remember where the dictionary pointer will go + dict_p_p <- tellBin bh + put_ bh dict_p_p -- Placeholder for ptr to dictionary + + -- Remember where the symbol table pointer will go + symtab_p_p <- tellBin bh + put_ bh symtab_p_p + + -- Make some intial state + ud <- newWriteState + + -- Put the main thing, + bh <- return $ setUserData bh ud + put_ bh mod_iface + + -- Write the symtab pointer at the fornt of the file + symtab_p <- tellBin bh -- This is where the symtab will start + putAt bh symtab_p_p symtab_p -- Fill in the placeholder + seekBin bh symtab_p -- Seek back to the end of the file + + -- Write the symbol table itself + symtab_next <- readFastMutInt (ud_symtab_next ud) + symtab_map <- readIORef (ud_symtab_map ud) + putSymbolTable bh symtab_next symtab_map + debugTraceMsg dflags 3 (text "writeBinIface:" <+> int symtab_next + <+> text "Names") + + -- NB. write the dictionary after the symbol table, because + -- writing the symbol table may create more dictionary entries. + + -- Write the dictionary pointer at the fornt of the file + dict_p <- tellBin bh -- This is where the dictionary will start + putAt bh dict_p_p dict_p -- Fill in the placeholder + seekBin bh dict_p -- Seek back to the end of the file + + -- Write the dictionary itself + dict_next <- readFastMutInt (ud_dict_next ud) + dict_map <- readIORef (ud_dict_map ud) + putDictionary bh dict_next dict_map + debugTraceMsg dflags 3 (text "writeBinIface:" <+> int dict_next + <+> text "dict entries") + + -- And send the result to the file + writeBinMem bh hi_path + +initBinMemSize = (1024*1024) :: Int + +-- The *host* architecture version: +#include "MachDeps.h" + +#if WORD_SIZE_IN_BITS == 32 +binaryInterfaceMagic = 0x1face :: Word32 +#elif WORD_SIZE_IN_BITS == 64 +binaryInterfaceMagic = 0x1face64 :: Word32 +#endif + +-- ----------------------------------------------------------------------------- +-- The symbol table + +putSymbolTable :: BinHandle -> Int -> UniqFM (Int,Name) -> IO () +putSymbolTable bh next_off symtab = do + put_ bh next_off + let names = elems (array (0,next_off-1) (eltsUFM symtab)) + mapM_ (\n -> serialiseName bh n symtab) names + +getSymbolTable :: BinHandle -> NameCache -> IO (NameCache, Array Int Name) +getSymbolTable bh namecache = do + sz <- get bh + od_names <- sequence (replicate sz (get bh)) + let + arr = listArray (0,sz-1) names + (namecache', names) = + mapAccumR (fromOnDiskName arr) namecache od_names + -- + return (namecache', arr) + +type OnDiskName = (PackageId, ModuleName, OccName) + +fromOnDiskName + :: Array Int Name + -> NameCache + -> OnDiskName + -> (NameCache, Name) +fromOnDiskName arr nc (pid, mod_name, occ) = + let + mod = mkModule pid mod_name + cache = nsNames nc + in + case lookupOrigNameCache cache mod occ of + Just name -> (nc, name) + Nothing -> + let + us = nsUniqs nc + uniq = uniqFromSupply us + name = mkExternalName uniq mod occ noSrcLoc + new_cache = extendNameCache cache mod occ name + in + case splitUniqSupply us of { (us',_) -> + ( nc{ nsUniqs = us', nsNames = new_cache }, name ) + } + +serialiseName :: BinHandle -> Name -> UniqFM (Int,Name) -> IO () +serialiseName bh name symtab = do + let mod = nameModule name + put_ bh (modulePackageId mod, moduleName mod, nameOccName name) + +-- ----------------------------------------------------------------------------- +-- All the binary instances -- BasicTypes {-! for IPName derive: Binary !-} @@ -504,36 +668,6 @@ instance Binary CostCentre where -- IfaceTypes and friends ------------------------------------------------------------------------- -instance Binary IfaceExtName where - put_ bh (ExtPkg mod occ) = do - putByte bh 0 - put_ bh mod - put_ bh occ - put_ bh (HomePkg mod occ vers) = do - putByte bh 1 - put_ bh mod - put_ bh occ - put_ bh vers - put_ bh (LocalTop occ) = do - putByte bh 2 - put_ bh occ - put_ bh (LocalTopSub occ _) = do -- Write LocalTopSub just like LocalTop - putByte bh 2 - put_ bh occ - - get bh = do - h <- getByte bh - case h of - 0 -> do mod <- get bh - occ <- get bh - return (ExtPkg mod occ) - 1 -> do mod <- get bh - occ <- get bh - vers <- get bh - return (HomePkg mod occ vers) - _ -> do occ <- get bh - return (LocalTop occ) - instance Binary IfaceBndr where put_ bh (IfaceIdBndr aa) = do putByte bh 0 @@ -884,17 +1018,23 @@ instance Binary IfaceNote where -- IfaceDecl and friends ------------------------------------------------------------------------- +-- A bit of magic going on here: there's no need to store the OccName +-- for a decl on the disk, since we can infer the namespace from the +-- context; however it is useful to have the OccName in the IfaceDecl +-- to avoid re-building it in various places. So we build the OccName +-- when de-serialising. + instance Binary IfaceDecl where put_ bh (IfaceId name ty idinfo) = do putByte bh 0 - put_ bh name + put_ bh (occNameFS name) put_ bh ty put_ bh idinfo put_ bh (IfaceForeign ae af) = error "Binary.put_(IfaceDecl): IfaceForeign" put_ bh (IfaceData a1 a2 a3 a4 a5 a6 a7 a8) = do putByte bh 2 - put_ bh a1 + put_ bh (occNameFS a1) put_ bh a2 put_ bh a3 put_ bh a4 @@ -904,14 +1044,14 @@ instance Binary IfaceDecl where put_ bh a8 put_ bh (IfaceSyn aq ar as at) = do putByte bh 3 - put_ bh aq + put_ bh (occNameFS aq) put_ bh ar put_ bh as put_ bh at put_ bh (IfaceClass a1 a2 a3 a4 a5 a6 a7) = do putByte bh 4 put_ bh a1 - put_ bh a2 + put_ bh (occNameFS a2) put_ bh a3 put_ bh a4 put_ bh a5 @@ -923,7 +1063,8 @@ instance Binary IfaceDecl where 0 -> do name <- get bh ty <- get bh idinfo <- get bh - return (IfaceId name ty idinfo) + occ <- return $! mkOccNameFS varName name + return (IfaceId occ ty idinfo) 1 -> error "Binary.get(TyClDecl): ForeignType" 2 -> do a1 <- get bh @@ -934,13 +1075,15 @@ instance Binary IfaceDecl where a6 <- get bh a7 <- get bh a8 <- get bh - return (IfaceData a1 a2 a3 a4 a5 a6 a7 a8) + occ <- return $! mkOccNameFS tcName a1 + return (IfaceData occ a2 a3 a4 a5 a6 a7 a8) 3 -> do aq <- get bh ar <- get bh as <- get bh at <- get bh - return (IfaceSyn aq ar as at) + occ <- return $! mkOccNameFS tcName aq + return (IfaceSyn occ ar as at) _ -> do a1 <- get bh a2 <- get bh @@ -949,7 +1092,8 @@ instance Binary IfaceDecl where a5 <- get bh a6 <- get bh a7 <- get bh - return (IfaceClass a1 a2 a3 a4 a5 a6 a7) + occ <- return $! mkOccNameFS clsName a2 + return (IfaceClass a1 occ a3 a4 a5 a6 a7) instance Binary IfaceInst where put_ bh (IfaceInst cls tys dfun flag orph) = do @@ -1028,14 +1172,15 @@ instance Binary IfaceConDecl where instance Binary IfaceClassOp where put_ bh (IfaceClassOp n def ty) = do - put_ bh n + put_ bh (occNameFS n) put_ bh def put_ bh ty get bh = do n <- get bh def <- get bh ty <- get bh - return (IfaceClassOp n def ty) + occ <- return $! mkOccNameFS varName n + return (IfaceClassOp occ def ty) instance Binary IfaceRule where put_ bh (IfaceRule a1 a2 a3 a4 a5 a6 a7) = do diff --git a/compiler/iface/IfaceEnv.lhs b/compiler/iface/IfaceEnv.lhs index 61759658d3..fe0b0cdb22 100644 --- a/compiler/iface/IfaceEnv.lhs +++ b/compiler/iface/IfaceEnv.lhs @@ -3,31 +3,31 @@ \begin{code} module IfaceEnv ( newGlobalBinder, newIPName, newImplicitBinder, - lookupIfaceTop, lookupIfaceExt, - lookupOrig, lookupIfaceTc, + lookupIfaceTop, + lookupOrig, lookupOrigNameCache, extendNameCache, newIfaceName, newIfaceNames, extendIfaceIdEnv, extendIfaceTyVarEnv, tcIfaceLclId, tcIfaceTyVar, - lookupAvail, ifaceExportNames, + ifaceExportNames, -- Name-cache stuff allocateGlobalBinder, initNameCache, + getNameCache, setNameCache ) where #include "HsVersions.h" import TcRnMonad -import IfaceType ( IfaceExtName(..), IfaceTyCon(..), ifaceTyConName ) import TysWiredIn ( tupleTyCon, tupleCon ) import HscTypes ( NameCache(..), HscEnv(..), GenAvailInfo(..), - IfaceExport, OrigNameCache ) + IfaceExport, OrigNameCache, AvailInfo ) +import Type ( mkOpenTvSubst, substTy ) import TyCon ( TyCon, tyConName ) import DataCon ( dataConWorkId, dataConName ) import Var ( TyVar, Id, varName ) -import Name ( Name, nameUnique, nameModule, - nameOccName, nameSrcLoc, - getOccName, nameParent_maybe, +import Name ( Name, nameUnique, nameModule, + nameOccName, nameSrcLoc, getOccName, isWiredInName, mkIPName, mkExternalName, mkInternalName ) import NameSet ( NameSet, emptyNameSet, addListToNameSet ) @@ -54,7 +54,7 @@ import Outputable %********************************************************* \begin{code} -newGlobalBinder :: Module -> OccName -> Maybe Name -> SrcLoc -> TcRnIf a b Name +newGlobalBinder :: Module -> OccName -> SrcLoc -> TcRnIf a b Name -- Used for source code and interface files, to make the -- Name for a thing, given its Module and OccName -- @@ -62,25 +62,25 @@ newGlobalBinder :: Module -> OccName -> Maybe Name -> SrcLoc -> TcRnIf a b Name -- because we may have seen an occurrence before, but now is the -- moment when we know its Module and SrcLoc in their full glory -newGlobalBinder mod occ mb_parent loc +newGlobalBinder mod occ loc = do { mod `seq` occ `seq` return () -- See notes with lookupOrig_help - -- ; traceIf (text "newGlobalBinder" <+> ppr mod <+> ppr occ <+> ppr loc) + ; traceIf (text "newGlobalBinder" <+> ppr mod <+> ppr occ <+> ppr loc) ; name_supply <- getNameCache ; let (name_supply', name) = allocateGlobalBinder name_supply mod occ - mb_parent loc + loc ; setNameCache name_supply' ; return name } allocateGlobalBinder :: NameCache - -> Module -> OccName -> Maybe Name -> SrcLoc + -> Module -> OccName -> SrcLoc -> (NameCache, Name) -allocateGlobalBinder name_supply mod occ mb_parent loc +allocateGlobalBinder name_supply mod occ loc = case lookupOrigNameCache (nsNames name_supply) mod occ of -- A hit in the cache! We are at the binding site of the name. - -- This is the moment when we know the defining parent and SrcLoc - -- of the Name, so we set these fields in the Name we return. + -- This is the moment when we know the SrcLoc + -- of the Name, so we set this field in the Name we return. -- -- Then (bogus) multiple bindings of the same Name -- get different SrcLocs can can be reported as such. @@ -98,8 +98,8 @@ allocateGlobalBinder name_supply mod occ mb_parent loc | otherwise -> (new_name_supply, name') where uniq = nameUnique name - name' = mkExternalName uniq mod occ mb_parent loc - new_cache = extend_name_cache (nsNames name_supply) mod occ name' + name' = mkExternalName uniq mod occ loc + new_cache = extendNameCache (nsNames name_supply) mod occ name' new_name_supply = name_supply {nsNames = new_cache} -- Miss in the cache! @@ -108,8 +108,8 @@ allocateGlobalBinder name_supply mod occ mb_parent loc where (us', us1) = splitUniqSupply (nsUniqs name_supply) uniq = uniqFromSupply us1 - name = mkExternalName uniq mod occ mb_parent loc - new_cache = extend_name_cache (nsNames name_supply) mod occ name + name = mkExternalName uniq mod occ loc + new_cache = extendNameCache (nsNames name_supply) mod occ name new_name_supply = name_supply {nsUniqs = us', nsNames = new_cache} @@ -119,67 +119,34 @@ newImplicitBinder :: Name -- Base name -- Called in BuildTyCl to allocate the implicit binders of type/class decls -- For source type/class decls, this is the first occurrence -- For iface ones, the LoadIface has alrady allocated a suitable name in the cache --- --- An *implicit* name has the base-name as parent newImplicitBinder base_name mk_sys_occ = newGlobalBinder (nameModule base_name) (mk_sys_occ (nameOccName base_name)) - (Just parent_name) (nameSrcLoc base_name) - where - parent_name = case nameParent_maybe base_name of - Just parent_name -> parent_name - Nothing -> base_name -ifaceExportNames :: [IfaceExport] -> TcRnIf gbl lcl NameSet -ifaceExportNames exports - = foldlM do_one emptyNameSet exports - where - do_one acc (mod, exports) = foldlM (do_avail mod) acc exports - do_avail mod acc avail = do { ns <- lookupAvail mod avail - ; return (addListToNameSet acc ns) } - -lookupAvail :: Module -> GenAvailInfo OccName -> TcRnIf a b [Name] --- Find all the names arising from an import --- Make sure the parent info is correct, even though we may not --- yet have read the interface for this module -lookupAvail mod (Avail n) = do { n' <- lookupOrig mod n; - ; return [n'] } -lookupAvail mod (AvailTC p_occ occs) - = do { p_name <- lookupOrig mod p_occ - ; let lookup_sub occ | occ == p_occ = return p_name - | otherwise = lookup_orig mod occ (Just p_name) - ; mappM lookup_sub occs } +ifaceExportNames :: [IfaceExport] -> TcRnIf gbl lcl [AvailInfo] +ifaceExportNames exports = do + mod_avails <- mapM (\(mod,avails) -> mapM (lookupAvail mod) avails) exports + return (concat mod_avails) + +-- Convert OccNames in GenAvailInfo to Names. +lookupAvail :: Module -> GenAvailInfo OccName -> TcRnIf a b AvailInfo +lookupAvail mod (Avail n) = do + n' <- lookupOrig mod n + return (Avail n') +lookupAvail mod (AvailTC p_occ occs) = do + p_name <- lookupOrig mod p_occ + let lookup_sub occ | occ == p_occ = return p_name + | otherwise = lookupOrig mod occ + subs <- mappM lookup_sub occs + return (AvailTC p_name subs) -- Remember that 'occs' is all the exported things, including -- the parent. It's possible to export just class ops without - -- the class, via C( op ). If the class was exported too we'd - -- have C( C, op ) - - -- The use of lookupOrigSub here (rather than lookupOrig) - -- ensures that the subordinate names record their parent; - -- and that in turn ensures that the GlobalRdrEnv - -- has the correct parent for all the names in its range. - -- For imported things, we may only suck in the interface later, if ever. - -- Reason for all this: - -- Suppose module M exports type A.T, and constructor A.MkT - -- Then, we know that A.MkT is a subordinate name of A.T, - -- even though we aren't at the binding site of A.T - -- And it's important, because we may simply re-export A.T - -- without ever sucking in the declaration itself. - - -lookupOrig :: Module -> OccName -> TcRnIf a b Name --- Even if we get a miss in the original-name cache, we --- make a new External Name. --- We fake up --- SrcLoc to noSrcLoc --- Parent no Nothing --- They'll be overwritten, in due course, by LoadIface.loadDecl. -lookupOrig mod occ = lookup_orig mod occ Nothing - -lookup_orig :: Module -> OccName -> Maybe Name -> TcRnIf a b Name --- Used when we know the parent of the thing we are looking up -lookup_orig mod occ mb_parent + -- the class, which shows up as C( op ) here. If the class was + -- exported too we'd have C( C, op ) + +lookupOrig :: Module -> OccName -> TcRnIf a b Name +lookupOrig mod occ = do { -- First ensure that mod and occ are evaluated -- If not, chaos can ensue: -- we read the name-cache @@ -187,21 +154,22 @@ lookup_orig mod occ mb_parent -- which does some stuff that modifies the name cache -- This did happen, with tycon_mod in TcIface.tcIfaceAlt (DataAlt..) mod `seq` occ `seq` return () + ; traceIf (text "lookup_orig" <+> ppr mod <+> ppr occ) - ; name_supply <- getNameCache - ; case lookupOrigNameCache (nsNames name_supply) mod occ of { - Just name -> returnM name ; - Nothing -> do - - { let { (us', us1) = splitUniqSupply (nsUniqs name_supply) - ; uniq = uniqFromSupply us1 - ; name = mkExternalName uniq mod occ mb_parent noSrcLoc - ; new_cache = extend_name_cache (nsNames name_supply) mod occ name - ; new_name_supply = name_supply {nsUniqs = us', nsNames = new_cache} - } - ; setNameCache new_name_supply - ; return name } - }} + ; name_cache <- getNameCache + ; case lookupOrigNameCache (nsNames name_cache) mod occ of { + Just name -> returnM name; + Nothing -> + let + us = nsUniqs name_cache + uniq = uniqFromSupply us + name = mkExternalName uniq mod occ noSrcLoc + new_cache = extendNameCache (nsNames name_cache) mod occ name + in + case splitUniqSupply us of { (us',_) -> do + setNameCache name_cache{ nsUniqs = us', nsNames = new_cache } + return name + }}} newIPName :: IPName OccName -> TcRnIf m n (IPName Name) newIPName occ_name_ip @@ -246,10 +214,10 @@ lookupOrigNameCache nc mod occ -- The normal case extendOrigNameCache :: OrigNameCache -> Name -> OrigNameCache extendOrigNameCache nc name - = extend_name_cache nc (nameModule name) (nameOccName name) name + = extendNameCache nc (nameModule name) (nameOccName name) name -extend_name_cache :: OrigNameCache -> Module -> OccName -> Name -> OrigNameCache -extend_name_cache nc mod occ name +extendNameCache :: OrigNameCache -> Module -> OccName -> Name -> OrigNameCache +extendNameCache nc mod occ name = extendModuleEnv_C combine nc mod (unitOccEnv occ name) where combine occ_env _ = extendOccEnv occ_env occ name @@ -324,16 +292,6 @@ extendIfaceTyVarEnv tyvars thing_inside %************************************************************************ \begin{code} -lookupIfaceTc :: IfaceTyCon -> IfL Name -lookupIfaceTc (IfaceTc ext) = lookupIfaceExt ext -lookupIfaceTc other_tc = return (ifaceTyConName other_tc) - -lookupIfaceExt :: IfaceExtName -> IfL Name -lookupIfaceExt (ExtPkg mod occ) = lookupOrig mod occ -lookupIfaceExt (HomePkg mod occ _) = lookupHomePackage mod occ -lookupIfaceExt (LocalTop occ) = lookupIfaceTop occ -lookupIfaceExt (LocalTopSub occ _) = lookupIfaceTop occ - lookupIfaceTop :: OccName -> IfL Name -- Look up a top-level name from the current Iface module lookupIfaceTop occ diff --git a/compiler/iface/IfaceSyn.lhs b/compiler/iface/IfaceSyn.lhs index 8ac4eecc87..a8426081a8 100644 --- a/compiler/iface/IfaceSyn.lhs +++ b/compiler/iface/IfaceSyn.lhs @@ -20,14 +20,14 @@ module IfaceSyn ( IfaceInfoItem(..), IfaceRule(..), IfaceInst(..), IfaceFamInst(..), -- Misc - visibleIfConDecls, + ifaceDeclSubBndrs, visibleIfConDecls, -- Equality - IfaceEq(..), (&&&), bool, eqListBy, eqMaybeBy, + GenIfaceEq(..), IfaceEq, (&&&), bool, eqListBy, eqMaybeBy, eqIfDecl, eqIfInst, eqIfRule, checkBootDecl, -- Pretty printing - pprIfaceExpr, pprIfaceDecl, pprIfaceDeclHead + pprIfaceExpr, pprIfaceDeclHead ) where #include "HsVersions.h" @@ -37,16 +37,23 @@ import IfaceType import NewDemand ( StrictSig, pprIfaceStrictSig ) import Class ( FunDep, DefMeth, pprFundeps ) -import OccName ( OccName, parenSymOcc, occNameFS, - OccSet, unionOccSets, unitOccSet, occSetElts ) +import OccName import UniqFM ( UniqFM, emptyUFM, addToUFM, lookupUFM ) +import Unique ( mkBuiltinUnique ) +import NameSet +import Name ( Name, NamedThing(..), isExternalName, + mkInternalName ) import CostCentre ( CostCentre, pprCostCentreCore ) import Literal ( Literal ) import ForeignCall ( ForeignCall ) -import BasicTypes ( Arity, Activation(..), StrictnessMark, OverlapFlag, - RecFlag(..), Boxity(..), tupleParens ) +import SrcLoc ( noSrcLoc ) +import BasicTypes import Outputable import FastString +import Maybes ( catMaybes ) + +import Data.List ( nub ) +import Data.Maybe ( isJust ) infixl 3 &&& infix 4 `eqIfExt`, `eqIfIdInfo`, `eqIfType` @@ -101,7 +108,8 @@ data IfaceDecl 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,7 +133,7 @@ visibleIfConDecls (IfNewTyCon c) = [c] data IfaceConDecl = IfCon { - ifConOcc :: OccName, -- Constructor name + ifConOcc :: OccName, -- Constructor name ifConInfix :: Bool, -- True <=> declared infix ifConUnivTvs :: [IfaceTvBndr], -- Universal tyvars ifConExTvs :: [IfaceTvBndr], -- Existential tyvars @@ -137,9 +145,9 @@ data IfaceConDecl -- 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 -- There's always a separate IfaceDecl for the DFun, which gives @@ -150,7 +158,7 @@ data IfaceInst -- and if the head does not change it won't be used if it wasn't before data IfaceFamInst - = IfaceFamInst { ifFamInstFam :: IfaceExtName -- Family tycon + = IfaceFamInst { ifFamInstFam :: Name -- Family tycon , ifFamInstTys :: [Maybe IfaceTyCon] -- Rough match types , ifFamInstTyCon :: IfaceTyCon -- Instance decl } @@ -160,7 +168,7 @@ data 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 @@ -186,7 +194,7 @@ data IfaceInfoItem | 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. @@ -196,7 +204,7 @@ data IfaceInfoItem -------------------------------- data IfaceExpr = IfaceLcl FastString - | IfaceExt IfaceExtName + | IfaceExt Name | IfaceType IfaceType | IfaceTuple Boxity [IfaceExpr] -- Saturated; type arguments omitted | IfaceLam IfaceBndr IfaceExpr @@ -218,25 +226,80 @@ type IfaceAlt = (IfaceConAlt, [FastString], IfaceExpr) -- 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)] -\end{code} - - -%************************************************************************ -%* * -\subsection[HsCore-print]{Printing Core unfoldings} -%* * -%************************************************************************ ------------------------------ Printing IfaceDecl ------------------------------------ +-- ----------------------------------------------------------------------------- +-- 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 + +ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ, + ifSigs = sigs, ifATs = ats }) + = co_occs ++ + [tc_occ, dc_occ, dcww_occ] ++ + [op | IfaceClassOp op _ _ <- sigs] ++ + [ifName at | at <- ats ] ++ + [mkSuperDictSelOcc n cls_occ | n <- [1..n_ctxt]] + 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 -- | is_newtype = mkDataConWrapperOcc dc_occ -- Newtypes have wrapper but no worker + | otherwise = mkDataConWorkerOcc dc_occ -- Otherwise worker but no wrapper + is_newtype = n_sigs + n_ctxt == 1 -- Sigh + +ifaceDeclSubBndrs IfaceData {ifCons = IfAbstractTyCon} + = [] +-- Newtype +ifaceDeclSubBndrs (IfaceData {ifName = tc_occ, + ifCons = IfNewTyCon ( + IfCon { ifConOcc = con_occ, + ifConFields = fields + }), + ifFamInst = famInst}) + = fields ++ [con_occ, mkDataConWorkerOcc con_occ, mkNewTyCoOcc tc_occ] + ++ famInstCo famInst tc_occ + +ifaceDeclSubBndrs (IfaceData {ifName = tc_occ, + ifCons = IfDataTyCon cons, + ifFamInst = famInst}) + = nub (concatMap ifConFields cons) -- Eliminate duplicate fields + ++ concatMap dc_occs cons + ++ famInstCo famInst tc_occ + where + dc_occs con_decl + | has_wrapper = [con_occ, work_occ, wrap_occ] + | otherwise = [con_occ, work_occ] + where + con_occ = ifConOcc con_decl + strs = ifConStricts con_decl + wrap_occ = mkDataConWrapperOcc con_occ + work_occ = mkDataConWorkerOcc con_occ + has_wrapper = any isMarkedStrict strs -- See MkId.mkDataConIds (sigh) + || not (null . ifConEqSpec $ con_decl) + || isJust famInst + -- ToDo: may miss strictness in existential dicts + +ifaceDeclSubBndrs _other = [] + +-- coercion for data/newtype family instances +famInstCo Nothing baseOcc = [] +famInstCo (Just _) baseOcc = [mkInstTyCoOcc baseOcc] + +----------------------------- Printing IfaceDecl ------------------------------ -\begin{code} instance Outputable IfaceDecl where ppr = pprIfaceDecl @@ -319,9 +382,10 @@ pprIfaceConDecl tc eq_ctxt = [(IfaceEqPred (IfaceTyVar (occNameFS tv)) ty) | (tv,ty) <- eq_spec] con_tau = foldr1 IfaceFunTy (arg_tys ++ [tc_app]) - tc_app = IfaceTyConApp (IfaceTc (LocalTop tc)) + tc_app = IfaceTyConApp (IfaceTc tc_name) [IfaceTyVar tv | (tv,_) <- univ_tvs] - -- Gruesome, but just for debug print + tc_name = mkInternalName (mkBuiltinUnique 1) tc noSrcLoc + -- Really Gruesome, but just for debug print instance Outputable IfaceRule where ppr (IfaceRule { ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs, @@ -457,23 +521,25 @@ ppr_hs_info (HsWorker w a) = ptext SLIT("Worker:") <+> ppr w <+> int a %* * %************************************************************************ -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 (occSetElts occset) + ppr (EqBut occset) = ptext SLIT("EqBut") <+> ppr (nameSetToList occset) bool :: Bool -> IfaceEq bool True = Equal @@ -491,23 +557,18 @@ 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 - -\begin{code} --------------------- checkBootDecl :: IfaceDecl -- The boot decl -> IfaceDecl -- The real decl diff --git a/compiler/iface/IfaceType.lhs b/compiler/iface/IfaceType.lhs index ee37891aa7..64d88927f6 100644 --- a/compiler/iface/IfaceType.lhs +++ b/compiler/iface/IfaceType.lhs @@ -8,9 +8,7 @@ module IfaceType ( IfaceType(..), IfaceKind, IfacePredType(..), IfaceTyCon(..), IfaceContext, IfaceBndr(..), IfaceTvBndr, IfaceIdBndr, IfaceCoercion, - - IfaceExtName(..), mkIfaceExtName, isLocalIfaceExtName, - ifaceTyConName, ifaceTyConOccName, + ifaceTyConName, -- Conversion from Type -> IfaceType toIfaceType, toIfacePred, toIfaceContext, @@ -42,50 +40,6 @@ import Outputable import FastString \end{code} - -%************************************************************************ -%* * - IfaceExtName -%* * -%************************************************************************ - -\begin{code} -data IfaceExtName - = ExtPkg Module OccName - -- From an external package; no version # Also used for - -- wired-in things regardless of whether they are home-pkg or - -- not - - | HomePkg ModuleName OccName Version - -- From another module in home package; has version #; in all - -- other respects, HomePkg and ExtPkg are the same. Since this - -- is a home package name, we use ModuleName rather than Module - - | LocalTop OccName -- Top-level from the same module as - -- the enclosing IfaceDecl - - | LocalTopSub -- Same as LocalTop, but for a class method or constr - OccName -- Class-meth/constr name - OccName -- Parent class/datatype name - -- LocalTopSub is written into iface files as LocalTop; the parent - -- info is only used when computing version information in MkIface - -isLocalIfaceExtName :: IfaceExtName -> Bool -isLocalIfaceExtName (LocalTop _) = True -isLocalIfaceExtName (LocalTopSub _ _) = True -isLocalIfaceExtName other = False - -mkIfaceExtName name = ExtPkg (nameModule name) (nameOccName name) - -- Local helper for wired-in names - -ifaceExtOcc :: IfaceExtName -> OccName -ifaceExtOcc (ExtPkg _ occ) = occ -ifaceExtOcc (HomePkg _ occ _) = occ -ifaceExtOcc (LocalTop occ) = occ -ifaceExtOcc (LocalTopSub occ _) = occ -\end{code} - - %************************************************************************ %* * Local (nested) binders @@ -115,7 +69,7 @@ data IfaceType | IfaceFunTy IfaceType IfaceType data IfacePredType -- NewTypes are handled as ordinary TyConApps - = IfaceClassP IfaceExtName [IfaceType] + = IfaceClassP Name [IfaceType] | IfaceIParam (IPName OccName) IfaceType | IfaceEqPred IfaceType IfaceType @@ -124,14 +78,14 @@ type IfaceContext = [IfacePredType] -- NB: If you add a data constructor, remember to add a case to -- IfaceSyn.eqIfTc! data IfaceTyCon -- Abbreviations for common tycons with known names - = IfaceTc IfaceExtName -- The common case + = IfaceTc Name -- The common case | IfaceIntTc | IfaceBoolTc | IfaceCharTc | IfaceListTc | IfacePArrTc | IfaceTupTc Boxity Arity | IfaceLiftedTypeKindTc | IfaceOpenTypeKindTc | IfaceUnliftedTypeKindTc | IfaceUbxTupleKindTc | IfaceArgTypeKindTc -ifaceTyConName :: IfaceTyCon -> Name -- Works for all except IfaceTc +ifaceTyConName :: IfaceTyCon -> Name ifaceTyConName IfaceIntTc = intTyConName ifaceTyConName IfaceBoolTc = boolTyConName ifaceTyConName IfaceCharTc = charTyConName @@ -143,11 +97,7 @@ ifaceTyConName IfaceOpenTypeKindTc = openTypeKindTyConName ifaceTyConName IfaceUnliftedTypeKindTc = unliftedTypeKindTyConName ifaceTyConName IfaceUbxTupleKindTc = ubxTupleKindTyConName ifaceTyConName IfaceArgTypeKindTc = argTypeKindTyConName -ifaceTyConName (IfaceTc ext) = pprPanic "ifaceTyConName" (ppr ext) - -ifaceTyConOccName :: IfaceTyCon -> OccName -- Works for all! -ifaceTyConOccName (IfaceTc ext) = ifaceExtOcc ext -ifaceTyConOccName tycon = nameOccName . ifaceTyConName $ tycon +ifaceTyConName (IfaceTc ext) = ext \end{code} @@ -209,16 +159,6 @@ maybeParen ctxt_prec inner_prec pretty ----------------------------- Printing binders ------------------------------------ \begin{code} --- These instances are used only when printing for the user, either when --- debugging, or in GHCi when printing the results of a :info command -instance Outputable IfaceExtName where - ppr (ExtPkg mod occ) = ppr mod <> dot <> ppr occ - ppr (HomePkg mod occ vers) = ppr mod <> dot <> ppr occ <> braces (ppr vers) - ppr (LocalTop occ) = ppr occ -- Do we want to distinguish these - ppr (LocalTopSub occ _) = ppr occ -- from an ordinary occurrence? --- No need to worry about printing unqualified becuase that was handled --- in the transiation to IfaceSyn - instance Outputable IfaceBndr where ppr (IfaceIdBndr bndr) = pprIfaceIdBndr bndr ppr (IfaceTvBndr bndr) = char '@' <+> pprIfaceTvBndr bndr @@ -301,7 +241,7 @@ ppr_tc_app ctxt_prec tc tys ppr_tc :: IfaceTyCon -> SDoc -- Wrap infix type constructors in parens -ppr_tc tc@(IfaceTc ext_nm) = parenSymOcc (ifaceExtOcc ext_nm) (ppr tc) +ppr_tc tc@(IfaceTc ext_nm) = parenSymOcc (getOccName ext_nm) (ppr tc) ppr_tc tc = ppr tc ------------------- @@ -309,7 +249,7 @@ instance Outputable IfacePredType where -- Print without parens ppr (IfaceEqPred ty1 ty2)= hsep [ppr ty1, ptext SLIT(":=:"), ppr ty2] ppr (IfaceIParam ip ty) = hsep [ppr ip, dcolon, ppr ty] - ppr (IfaceClassP cls ts) = parenSymOcc (ifaceExtOcc cls) (ppr cls) + ppr (IfaceClassP cls ts) = parenSymOcc (getOccName cls) (ppr cls) <+> sep (map pprParendIfaceType ts) instance Outputable IfaceTyCon where @@ -338,26 +278,32 @@ pabrackets p = ptext SLIT("[:") <> p <> ptext SLIT(":]") \begin{code} ---------------- toIfaceTvBndr tyvar = (occNameFS (getOccName tyvar), toIfaceKind (tyVarKind tyvar)) -toIfaceIdBndr ext id = (occNameFS (getOccName id), toIfaceType ext (idType id)) +toIfaceIdBndr id = (occNameFS (getOccName id), toIfaceType (idType id)) toIfaceTvBndrs tyvars = map toIfaceTvBndr tyvars -toIfaceBndr ext var - | isId var = IfaceIdBndr (toIfaceIdBndr ext var) +toIfaceBndr var + | isId var = IfaceIdBndr (toIfaceIdBndr var) | otherwise = IfaceTvBndr (toIfaceTvBndr var) --- we had better not have to use ext for kinds -toIfaceKind = toIfaceType (\name -> pprPanic "toIfaceKind ext used on:" (ppr name)) +toIfaceKind = toIfaceType --------------------- -toIfaceType :: (Name -> IfaceExtName) -> Type -> IfaceType +toIfaceType :: Type -> IfaceType -- Synonyms are retained in the interface type -toIfaceType ext (TyVarTy tv) = IfaceTyVar (occNameFS (getOccName tv)) -toIfaceType ext (AppTy t1 t2) = IfaceAppTy (toIfaceType ext t1) (toIfaceType ext t2) -toIfaceType ext (FunTy t1 t2) = IfaceFunTy (toIfaceType ext t1) (toIfaceType ext t2) -toIfaceType ext (TyConApp tc tys) = IfaceTyConApp (toIfaceTyCon ext tc) (toIfaceTypes ext tys) -toIfaceType ext (ForAllTy tv t) = IfaceForAllTy (toIfaceTvBndr tv) (toIfaceType ext t) -toIfaceType ext (PredTy st) = IfacePredTy (toIfacePred ext st) -toIfaceType ext (NoteTy other_note ty) = toIfaceType ext ty +toIfaceType (TyVarTy tv) = + IfaceTyVar (occNameFS (getOccName tv)) +toIfaceType (AppTy t1 t2) = + IfaceAppTy (toIfaceType t1) (toIfaceType t2) +toIfaceType (FunTy t1 t2) = + IfaceFunTy (toIfaceType t1) (toIfaceType t2) +toIfaceType (TyConApp tc tys) = + IfaceTyConApp (toIfaceTyCon tc) (toIfaceTypes tys) +toIfaceType (ForAllTy tv t) = + IfaceForAllTy (toIfaceTvBndr tv) (toIfaceType t) +toIfaceType (PredTy st) = + IfacePredTy (toIfacePred st) +toIfaceType (NoteTy other_note ty) = + toIfaceType ty ---------------- -- A little bit of (perhaps optional) trickiness here. When @@ -367,20 +313,20 @@ toIfaceType ext (NoteTy other_note ty) = toIfaceType ext ty -- Hence a tuple tycon may 'miss' in toIfaceTyCon, but then -- toIfaceTyCon_name will still catch it. -toIfaceTyCon :: (Name -> IfaceExtName) -> TyCon -> IfaceTyCon -toIfaceTyCon ext tc +toIfaceTyCon :: TyCon -> IfaceTyCon +toIfaceTyCon tc | isTupleTyCon tc = IfaceTupTc (tupleTyConBoxity tc) (tyConArity tc) - | otherwise = toIfaceTyCon_name ext (tyConName tc) + | otherwise = toIfaceTyCon_name (tyConName tc) -toIfaceTyCon_name :: (Name -> IfaceExtName) -> Name -> IfaceTyCon -toIfaceTyCon_name ext nm +toIfaceTyCon_name :: Name -> IfaceTyCon +toIfaceTyCon_name nm | Just (ATyCon tc) <- wiredInNameTyThing_maybe nm - = toIfaceWiredInTyCon ext tc nm + = toIfaceWiredInTyCon tc nm | otherwise - = IfaceTc (ext nm) + = IfaceTc nm -toIfaceWiredInTyCon :: (Name -> IfaceExtName) -> TyCon -> Name -> IfaceTyCon -toIfaceWiredInTyCon ext tc nm +toIfaceWiredInTyCon :: TyCon -> Name -> IfaceTyCon +toIfaceWiredInTyCon tc nm | isTupleTyCon tc = IfaceTupTc (tupleTyConBoxity tc) (tyConArity tc) | nm == intTyConName = IfaceIntTc | nm == boolTyConName = IfaceBoolTc @@ -392,18 +338,21 @@ toIfaceWiredInTyCon ext tc nm | nm == openTypeKindTyConName = IfaceOpenTypeKindTc | nm == argTypeKindTyConName = IfaceArgTypeKindTc | nm == ubxTupleKindTyConName = IfaceUbxTupleKindTc - | otherwise = IfaceTc (ext nm) + | otherwise = IfaceTc nm ---------------- -toIfaceTypes ext ts = map (toIfaceType ext) ts +toIfaceTypes ts = map toIfaceType ts ---------------- -toIfacePred ext (ClassP cls ts) = IfaceClassP (ext (getName cls)) (toIfaceTypes ext ts) -toIfacePred ext (IParam ip t) = IfaceIParam (mapIPName getOccName ip) (toIfaceType ext t) -toIfacePred ext (EqPred ty1 ty2) = IfaceEqPred (toIfaceType ext ty1) (toIfaceType ext ty2) +toIfacePred (ClassP cls ts) = + IfaceClassP (getName cls) (toIfaceTypes ts) +toIfacePred (IParam ip t) = + IfaceIParam (mapIPName getOccName ip) (toIfaceType t) +toIfacePred (EqPred ty1 ty2) = + IfaceEqPred (toIfaceType ty1) (toIfaceType ty2) ---------------- -toIfaceContext :: (Name -> IfaceExtName) -> ThetaType -> IfaceContext -toIfaceContext ext cs = map (toIfacePred ext) cs +toIfaceContext :: ThetaType -> IfaceContext +toIfaceContext cs = map toIfacePred cs \end{code} diff --git a/compiler/iface/LoadIface.lhs b/compiler/iface/LoadIface.lhs index e322276dea..5b19c894fa 100644 --- a/compiler/iface/LoadIface.lhs +++ b/compiler/iface/LoadIface.lhs @@ -11,7 +11,7 @@ module LoadIface ( loadDecls, -- Should move to TcIface and be renamed initExternalPackageState, - ifaceStats, pprModIface, showIface -- Print the iface in Foo.hi + ifaceStats, pprModIface, showIface ) where #include "HsVersions.h" @@ -20,9 +20,8 @@ import {-# SOURCE #-} TcIface( tcIfaceDecl, tcIfaceRules, tcIfaceInst, tcIfaceFamInst ) import DynFlags ( DynFlags(..), DynFlag( Opt_IgnoreInterfacePragmas ) ) -import IfaceSyn ( IfaceDecl(..), IfaceConDecl(..), IfaceClassOp(..), - IfaceConDecls(..), IfaceFamInst(..) ) -import IfaceEnv ( newGlobalBinder, lookupIfaceTc ) +import IfaceSyn +import IfaceEnv ( newGlobalBinder ) import HscTypes ( ModIface(..), TyThing, IfaceExport, Usage(..), Deprecs(..), Dependencies(..), emptyModIface, EpsStats(..), GenAvailInfo(..), @@ -62,8 +61,8 @@ import UniqFM import StaticFlags ( opt_HiVersion ) import Outputable import BinIface ( readBinIface, v_IgnoreHiWay ) -import Binary ( getBinFileWithDict ) -import Panic ( ghcError, tryMost, showException, GhcException(..) ) +import Binary +import Panic ( ghcError, showException, GhcException(..) ) import List ( nub ) import Maybe ( isJust ) import DATA_IOREF ( writeIORef ) @@ -306,12 +305,9 @@ loadDecl :: Bool -- Don't load pragmas into the decl pool loadDecl ignore_prags mod (_version, decl) = do { -- Populate the name cache with final versions of all -- the names associated with the decl - main_name <- mk_new_bndr mod Nothing (ifName decl) - ; parent_name <- case ifFamily decl of -- make family the parent - Just famTyCon -> lookupIfaceTc famTyCon - _ -> return main_name - ; implicit_names <- mapM (mk_new_bndr mod (Just parent_name)) - (ifaceDeclSubBndrs decl) + main_name <- mk_new_bndr mod (ifName decl) + ; traceIf (text "Loading decl for " <> ppr main_name) + ; implicit_names <- mapM (mk_new_bndr mod) (ifaceDeclSubBndrs decl) -- Typecheck the thing, lazily -- NB. Firstly, the laziness is there in case we never need the @@ -341,8 +337,8 @@ loadDecl ignore_prags mod (_version, decl) -- * parent -- * location -- imported name, to fix the module correctly in the cache - mk_new_bndr mod mb_parent occ - = newGlobalBinder mod occ mb_parent + mk_new_bndr mod occ + = newGlobalBinder mod occ (importedSrcLoc (showSDoc (ppr (moduleName mod)))) -- ToDo: qualify with the package name if necessary @@ -357,70 +353,6 @@ bumpDeclStats name ; updateEps_ (\eps -> let stats = eps_stats eps in eps { eps_stats = stats { n_decls_out = n_decls_out stats + 1 } }) } - ------------------ -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 --- --- If you change this, make sure you change HscTypes.implicitTyThings in sync - -ifaceDeclSubBndrs (IfaceClass {ifCtxt = sc_ctxt, ifName = cls_occ, - ifSigs = sigs, ifATs = ats }) - = co_occs ++ - [tc_occ, dc_occ, dcww_occ] ++ - [op | IfaceClassOp op _ _ <- sigs] ++ - [ifName at | at <- ats ] ++ - [mkSuperDictSelOcc n cls_occ | n <- [1..n_ctxt]] - 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 -- | is_newtype = mkDataConWrapperOcc dc_occ -- Newtypes have wrapper but no worker - | otherwise = mkDataConWorkerOcc dc_occ -- Otherwise worker but no wrapper - is_newtype = n_sigs + n_ctxt == 1 -- Sigh - -ifaceDeclSubBndrs IfaceData {ifCons = IfAbstractTyCon} - = [] --- Newtype -ifaceDeclSubBndrs (IfaceData {ifName = tc_occ, - ifCons = IfNewTyCon ( - IfCon { ifConOcc = con_occ, - ifConFields = fields - }), - ifFamInst = famInst}) - = fields ++ [con_occ, mkDataConWorkerOcc con_occ, mkNewTyCoOcc tc_occ] - ++ famInstCo famInst tc_occ - -ifaceDeclSubBndrs (IfaceData {ifName = tc_occ, - ifCons = IfDataTyCon cons, - ifFamInst = famInst}) - = nub (concatMap ifConFields cons) -- Eliminate duplicate fields - ++ concatMap dc_occs cons - ++ famInstCo famInst tc_occ - where - dc_occs con_decl - | has_wrapper = [con_occ, work_occ, wrap_occ] - | otherwise = [con_occ, work_occ] - where - con_occ = ifConOcc con_decl - strs = ifConStricts con_decl - wrap_occ = mkDataConWrapperOcc con_occ - work_occ = mkDataConWorkerOcc con_occ - has_wrapper = any isMarkedStrict strs -- See MkId.mkDataConIds (sigh) - || not (null . ifConEqSpec $ con_decl) - || isJust famInst - -- ToDo: may miss strictness in existential dicts - -ifaceDeclSubBndrs _other = [] - --- coercion for data/newtype family instances -famInstCo Nothing baseOcc = [] -famInstCo (Just _) baseOcc = [mkInstTyCoOcc baseOcc] \end{code} @@ -504,8 +436,7 @@ readIface :: Module -> FilePath -> IsBootInterface readIface wanted_mod file_path is_hi_boot_file = do { dflags <- getDOpts - ; ioToIOEnv $ do - { res <- tryMost (readBinIface file_path) + ; res <- tryMostM $ readBinIface file_path ; case res of Right iface | wanted_mod == actual_mod -> return (Succeeded iface) @@ -515,7 +446,7 @@ readIface wanted_mod file_path is_hi_boot_file err = hiModuleNameMismatchWarn wanted_mod actual_mod Left exn -> return (Failed (text (showException exn))) - }} + } \end{code} @@ -594,18 +525,16 @@ ifaceStats eps %************************************************************************ \begin{code} -showIface :: FilePath -> IO () --- Read binary interface, and print it out -showIface filename = do +-- | Read binary interface, and print it out +showIface :: HscEnv -> FilePath -> IO () +showIface hsc_env filename = do -- skip the version check; we don't want to worry about profiled vs. -- non-profiled interfaces, for example. writeIORef v_IgnoreHiWay True - iface <- Binary.getBinFileWithDict filename + iface <- initTcRnIf 's' hsc_env () () $ readBinIface filename printDump (pprModIface iface) - where \end{code} - \begin{code} pprModIface :: ModIface -> SDoc -- Show a ModIface diff --git a/compiler/iface/MkIface.lhs b/compiler/iface/MkIface.lhs index 11235cef2e..e99e8bf038 100644 --- a/compiler/iface/MkIface.lhs +++ b/compiler/iface/MkIface.lhs @@ -176,8 +176,7 @@ compiled with -O. I think this is the case.] #include "HsVersions.h" import IfaceSyn -- All of it -import IfaceType ( toIfaceTvBndrs, toIfaceType, toIfaceContext, - ifaceTyConOccName ) +import IfaceType import LoadIface ( readIface, loadInterface, pprModIface ) import Id ( Id, idName, idType, idInfo, idArity, isDataConWorkId_maybe, isFCallId_maybe ) import IdInfo ( IdInfo, CafInfo(..), WorkerInfo(..), @@ -209,41 +208,43 @@ import HscTypes ( ModIface(..), ModDetails(..), ModSummary(..), msHiFilePath, mkIfaceDepCache, mkIfaceFixCache, mkIfaceVerCache, typeEnvElts, - GenAvailInfo(..), availName, + GenAvailInfo(..), availName, AvailInfo, ExternalPackageState(..), Usage(..), IsBootInterface, Deprecs(..), IfaceDeprecs, Deprecations, - lookupIfaceByModule + lookupIfaceByModule, isImplicitTyThing ) import DynFlags ( GhcMode(..), DynFlags(..), DynFlag(..), dopt ) -import Name ( Name, nameModule, nameOccName, nameParent, - isExternalName, isInternalName, nameParent_maybe, isWiredInName, - isImplicitName, NamedThing(..) ) +import Name ( Name, nameModule, nameModule_maybe, nameOccName, + isExternalName, isInternalName, isWiredInName, + NamedThing(..) ) import NameEnv import NameSet import OccName ( OccName, OccEnv, mkOccEnv, lookupOccEnv, emptyOccEnv, extendOccEnv_C, OccSet, emptyOccSet, elemOccSet, occSetElts, - extendOccSet, extendOccSetList, + extendOccSet, extendOccSetList, mkOccSet, isEmptyOccSet, intersectOccSet, intersectsOccSet, + unionOccSets, unitOccSet, occNameFS, isTcOcc ) import Module -import Outputable -import BasicTypes ( Version, initialVersion, bumpVersion, isAlwaysActive, - Activation(..), RecFlag(..), boolToRecFlag ) -import Util ( createDirectoryHierarchy, directoryOf, sortLe, seqList, lengthIs ) -import BinIface ( writeBinIface ) +import BinIface ( readBinIface, writeBinIface, v_IgnoreHiWay ) import Unique ( Unique, Uniquable(..) ) import ErrUtils ( dumpIfSet_dyn, showPass ) import Digraph ( stronglyConnComp, SCC(..) ) import SrcLoc ( SrcSpan ) -import UniqFM import PackageConfig ( PackageId ) +import Outputable +import BasicTypes hiding ( SuccessFlag(..) ) +import UniqFM +import Util hiding ( eqListBy ) import FiniteMap import FastString +import Data.List ( partition ) +import DATA_IOREF ( writeIORef ) import Monad ( when ) import List ( insert ) import Maybes ( orElse, mapCatMaybes, isNothing, isJust, @@ -287,24 +288,20 @@ mkIface hsc_env maybe_old_iface -- to expose in the interface = do { eps <- hscEPS hsc_env - ; let { ext_nm_rhs = mkExtNameFn hsc_env eps this_mod - ; ext_nm_lhs = mkLhsNameFn this_mod - - ; decls = [ tyThingToIfaceDecl ext_nm_rhs thing - | thing <- typeEnvElts type_env, - let name = getName thing, - not (isImplicitName name || isWiredInName name) ] - -- Don't put implicit Ids and class tycons in the interface file - -- Nor wired-in things; the compiler knows about them anyhow - - ; fixities = [ (occ,fix) - | FixItem occ fix _ <- nameEnvElts fix_env] - ; deprecs = mkIfaceDeprec src_deprecs - ; iface_rules = map (coreRuleToIfaceRule - ext_nm_lhs ext_nm_rhs) rules - ; iface_insts = map (instanceToIfaceInst ext_nm_lhs) insts - ; iface_fam_insts = map (famInstToIfaceFamInst ext_nm_lhs) - fam_insts + ; let { entities = typeEnvElts type_env ; + decls = [ tyThingToIfaceDecl entity + | entity <- entities, + not (isImplicitTyThing entity + || isWiredInName (getName entity)) ] + -- Don't put implicit Ids and class tycons in + -- the interface file, Nor wired-in things; the + -- compiler knows about them anyhow + + ; fixities = [(occ,fix) | FixItem occ fix _ <- nameEnvElts fix_env] + ; deprecs = mkIfaceDeprec src_deprecs + ; iface_rules = map coreRuleToIfaceRule rules + ; iface_insts = map instanceToIfaceInst insts + ; iface_fam_insts = map famInstToIfaceFamInst fam_insts ; intermediate_iface = ModIface { mi_module = this_mod, @@ -333,9 +330,11 @@ mkIface hsc_env maybe_old_iface mi_fix_fn = mkIfaceFixCache fixities } -- Add version information + ; ext_ver_fn = mkParentVerFun hsc_env eps ; (new_iface, no_change_at_all, pp_diffs, pp_orphs) = _scc_ "versioninfo" - addVersionInfo maybe_old_iface intermediate_iface decls + addVersionInfo ext_ver_fn maybe_old_iface + intermediate_iface decls } -- Debug printing @@ -353,87 +352,61 @@ mkIface hsc_env maybe_old_iface dflags = hsc_dflags hsc_env deliberatelyOmitted x = panic ("Deliberately omitted: " ++ x) - ifFamInstTyConOcc = ifaceTyConOccName . ifFamInstTyCon + ifFamInstTyConOcc = nameOccName . ifaceTyConName . ifFamInstTyCon ----------------------------- -writeIfaceFile :: ModLocation -> ModIface -> IO () -writeIfaceFile location new_iface +writeIfaceFile :: DynFlags -> ModLocation -> ModIface -> IO () +writeIfaceFile dflags location new_iface = do createDirectoryHierarchy (directoryOf hi_file_path) - writeBinIface hi_file_path new_iface + writeBinIface dflags hi_file_path new_iface where hi_file_path = ml_hi_file location ------------------------------ -mkExtNameFn :: HscEnv -> ExternalPackageState -> Module -> Name -> IfaceExtName -mkExtNameFn hsc_env eps this_mod - = ext_nm - where - hpt = hsc_HPT hsc_env - pit = eps_PIT eps - - ext_nm name - | mod == this_mod = case nameParent_maybe name of - Nothing -> LocalTop occ - Just par -> LocalTopSub occ (nameOccName par) - | isWiredInName name = ExtPkg mod occ - | is_home mod = HomePkg mod_name occ vers - | otherwise = ExtPkg mod occ - where - dflags = hsc_dflags hsc_env - this_pkg = thisPackage dflags - is_home mod = modulePackageId mod == this_pkg - - mod = nameModule name - mod_name = moduleName mod - occ = nameOccName name - par_occ = nameOccName (nameParent name) - -- The version of the *parent* is the one want - vers = lookupVersion mod par_occ occ - - lookupVersion :: Module -> OccName -> OccName -> Version - -- Even though we're looking up a home-package thing, in - -- one-shot mode the imported interfaces may be in the PIT - lookupVersion mod par_occ occ - = mi_ver_fn iface par_occ `orElse` - pprPanic "lookupVers1" (ppr mod <+> ppr par_occ <+> ppr occ) - where - iface = lookupIfaceByModule (hsc_dflags hsc_env) hpt pit mod `orElse` - pprPanic "lookupVers2" (ppr mod <+> ppr par_occ <+> ppr occ) +-- ----------------------------------------------------------------------------- +-- Look up parents and versions of Names +-- This is like a global version of the mi_ver_fn field in each ModIface. +-- Given a Name, it finds the ModIface, and then uses mi_ver_fn to get +-- the parent and version info. ---------------------- --- mkLhsNameFn ignores versioning info altogether --- It is used for the LHS of instance decls and rules, where we --- there's no point in recording version info -mkLhsNameFn :: Module -> Name -> IfaceExtName -mkLhsNameFn this_mod name - | isInternalName name = pprTrace "mkLhsNameFn: unexpected internal" (ppr name) $ - LocalTop occ -- Should not happen - | mod == this_mod = LocalTop occ - | otherwise = ExtPkg mod occ +mkParentVerFun + :: HscEnv -- needed to look up versions + -> ExternalPackageState -- ditto + -> (Name -> (OccName,Version)) +mkParentVerFun hsc_env eps + = \name -> + let + mod = nameModule name + occ = nameOccName name + iface = lookupIfaceByModule (hsc_dflags hsc_env) hpt pit mod `orElse` + pprPanic "lookupVers2" (ppr mod <+> ppr occ) + in + mi_ver_fn iface occ `orElse` + pprPanic "lookupVers1" (ppr mod <+> ppr occ) where - mod = nameModule name - occ = nameOccName name - + hpt = hsc_HPT hsc_env + pit = eps_PIT eps ------------------------------ +----------------------------------------------------------------------------- -- Compute version numbers for local decls -addVersionInfo :: Maybe ModIface -- The old interface, read from M.hi - -> ModIface -- The new interface decls (lacking decls) - -> [IfaceDecl] -- The new decls - -> (ModIface, - Bool, -- True <=> no changes at all; no need to write new Iface - SDoc, -- Differences - Maybe SDoc) -- Warnings about orphans - -addVersionInfo Nothing new_iface new_decls +addVersionInfo + :: (Name -> (OccName,Version)) -- lookup parents and versions of names + -> Maybe ModIface -- The old interface, read from M.hi + -> ModIface -- The new interface (lacking decls) + -> [IfaceDecl] -- The new decls + -> (ModIface, -- Updated interface + Bool, -- True <=> no changes at all; no need to write Iface + SDoc, -- Differences + Maybe SDoc) -- Warnings about orphans + +addVersionInfo ver_fn Nothing new_iface new_decls -- No old interface, so definitely write a new one! = (new_iface { mi_orphan = anyNothing ifInstOrph (mi_insts new_iface) - || anyNothing ifRuleOrph (mi_rules new_iface), - mi_decls = [(initialVersion, decl) | decl <- new_decls], - mi_ver_fn = \n -> Just initialVersion }, + || anyNothing ifRuleOrph (mi_rules new_iface), + mi_decls = [(initialVersion, decl) | decl <- new_decls], + mi_ver_fn = mkIfaceVerCache (zip (repeat initialVersion) new_decls)}, False, ptext SLIT("No old interface file"), pprOrphans orph_insts orph_rules) @@ -441,7 +414,8 @@ addVersionInfo Nothing new_iface new_decls orph_insts = filter (isNothing . ifInstOrph) (mi_insts new_iface) orph_rules = filter (isNothing . ifRuleOrph) (mi_rules new_iface) -addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, +addVersionInfo ver_fn (Just old_iface@(ModIface { + mi_mod_vers = old_mod_vers, mi_exp_vers = old_exp_vers, mi_rule_vers = old_rule_vers, mi_decls = old_decls, @@ -449,29 +423,35 @@ addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, mi_fix_fn = old_fixities })) new_iface@(ModIface { mi_fix_fn = new_fixities }) new_decls - - | no_change_at_all = (old_iface, True, ptext SLIT("Interface file unchanged"), pp_orphs) - | otherwise = (final_iface, False, vcat [ptext SLIT("Interface file has changed"), - nest 2 pp_diffs], pp_orphs) - where - final_iface = new_iface { mi_mod_vers = bump_unless no_output_change old_mod_vers, - mi_exp_vers = bump_unless no_export_change old_exp_vers, - mi_rule_vers = bump_unless no_rule_change old_rule_vers, - mi_orphan = not (null new_orph_rules && null new_orph_insts), - mi_decls = decls_w_vers, - mi_ver_fn = mkIfaceVerCache decls_w_vers } + | no_change_at_all + = (old_iface, True, ptext SLIT("Interface file unchanged"), pp_orphs) + | otherwise + = (final_iface, False, vcat [ptext SLIT("Interface file has changed"), + nest 2 pp_diffs], pp_orphs) + where + final_iface = new_iface { + mi_mod_vers = bump_unless no_output_change old_mod_vers, + mi_exp_vers = bump_unless no_export_change old_exp_vers, + mi_rule_vers = bump_unless no_rule_change old_rule_vers, + mi_orphan = not (null new_orph_rules && null new_orph_insts), + mi_decls = decls_w_vers, + mi_ver_fn = mkIfaceVerCache decls_w_vers } decls_w_vers = [(add_vers decl, decl) | decl <- new_decls] ------------------- - (old_non_orph_insts, old_orph_insts) = mkOrphMap ifInstOrph (mi_insts old_iface) - (new_non_orph_insts, new_orph_insts) = mkOrphMap ifInstOrph (mi_insts new_iface) + (old_non_orph_insts, old_orph_insts) = + mkOrphMap ifInstOrph (mi_insts old_iface) + (new_non_orph_insts, new_orph_insts) = + mkOrphMap ifInstOrph (mi_insts new_iface) same_insts occ = eqMaybeBy (eqListBy eqIfInst) (lookupOccEnv old_non_orph_insts occ) (lookupOccEnv new_non_orph_insts occ) - (old_non_orph_rules, old_orph_rules) = mkOrphMap ifRuleOrph (mi_rules old_iface) - (new_non_orph_rules, new_orph_rules) = mkOrphMap ifRuleOrph (mi_rules new_iface) + (old_non_orph_rules, old_orph_rules) = + mkOrphMap ifRuleOrph (mi_rules old_iface) + (new_non_orph_rules, new_orph_rules) = + mkOrphMap ifRuleOrph (mi_rules new_iface) same_rules occ = eqMaybeBy (eqListBy eqIfRule) (lookupOccEnv old_non_orph_rules occ) (lookupOccEnv new_non_orph_rules occ) @@ -479,10 +459,11 @@ addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, -- Computing what changed no_output_change = no_decl_change && no_rule_change && no_export_change && no_deprec_change - no_export_change = mi_exports new_iface == mi_exports old_iface -- Kept sorted + no_export_change = mi_exports new_iface == mi_exports old_iface + -- Kept sorted no_decl_change = isEmptyOccSet changed_occs - no_rule_change = not (changedWrt changed_occs (eqListBy eqIfRule old_orph_rules new_orph_rules) - || changedWrt changed_occs (eqListBy eqIfInst old_orph_insts new_orph_insts)) + no_rule_change = not (changedWrtNames changed_occs (eqListBy eqIfRule old_orph_rules new_orph_rules) + || changedWrtNames changed_occs (eqListBy eqIfInst old_orph_insts new_orph_insts)) no_deprec_change = mi_deprecs new_iface == mi_deprecs old_iface -- If the usages havn't changed either, we don't need to write the interface file @@ -506,28 +487,32 @@ addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, ------------------- -- Adding version info - new_version = bumpVersion old_mod_vers -- Start from the old module version, not from zero - -- so that if you remove f, and then add it again, - -- you don't thereby reduce f's version number + new_version = bumpVersion old_mod_vers + -- Start from the old module version, not from + -- zero so that if you remove f, and then add + -- it again, you don't thereby reduce f's + -- version number + add_vers decl | occ `elemOccSet` changed_occs = new_version - | otherwise = expectJust "add_vers" (old_decl_vers occ) + | otherwise = snd (expectJust "add_vers" (old_decl_vers occ)) -- If it's unchanged, there jolly well where -- should be an old version number occ = ifName decl ------------------- - changed_occs :: OccSet - changed_occs = computeChangedOccs eq_info - + -- Deciding which declarations have changed + + -- For each local decl, the IfaceEq gives the list of things that + -- must be unchanged for the declaration as a whole to be unchanged. eq_info :: [(OccName, IfaceEq)] eq_info = map check_eq new_decls - check_eq new_decl | Just old_decl <- lookupOccEnv old_decl_env occ - = (occ, new_decl `eqIfDecl` old_decl &&& - eq_indirects new_decl) - | otherwise {- No corresponding old decl -} - = (occ, NotEqual) - where - occ = ifName new_decl + check_eq new_decl + | Just old_decl <- lookupOccEnv old_decl_env occ + = (occ, new_decl `eqIfDecl` old_decl &&& eq_indirects new_decl) + | otherwise {- No corresponding old decl -} + = (occ, NotEqual) + where + occ = ifName new_decl eq_indirects :: IfaceDecl -> IfaceEq -- When seeing if two decls are the same, remember to @@ -544,7 +529,12 @@ addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, eq_ind_occ :: OccName -> IfaceEq -- For class ops and Ids; check fixity and rules eq_ind_occ occ = same_fixity occ &&& same_rules occ eq_ind_occs = foldr ((&&&) . eq_ind_occ) Equal - + + -- The Occs of declarations that changed. + changed_occs :: OccSet + changed_occs = computeChangedOccs ver_fn (mi_module new_iface) + (mi_usages old_iface) eq_info + ------------------- -- Diffs pp_decl_diffs :: SDoc -- Nothing => no changes @@ -564,9 +554,10 @@ addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, where occ = ifName new_decl why = case lookupOccEnv eq_env occ of - Just (EqBut occs) -> sep [ppr occ <> colon, ptext SLIT("Free vars (only) changed:"), + Just (EqBut names) -> sep [ppr occ <> colon, ptext SLIT("Free vars (only) changed:"), nest 2 (braces (fsep (map ppr (occSetElts (occs `intersectOccSet` changed_occs)))))] + where occs = mkOccSet (map nameOccName (nameSetToList names)) Just NotEqual | Just old_decl <- lookupOccEnv old_decl_env occ -> vcat [ptext SLIT("Old:") <+> ppr old_decl, @@ -577,6 +568,7 @@ addVersionInfo (Just old_iface@(ModIface { mi_mod_vers = old_mod_vers, pp_orphs = pprOrphans new_orph_insts new_orph_rules + pprOrphans insts rules | null insts && null rules = Nothing | otherwise @@ -589,32 +581,82 @@ pprOrphans insts rules 2 (vcat (map ppr rules)) ] -computeChangedOccs :: [(OccName, IfaceEq)] -> OccSet -computeChangedOccs eq_info +computeChangedOccs + :: (Name -> (OccName,Version)) -- get parents and versions + -> Module -- This module + -> [Usage] -- Usages from old iface + -> [(OccName, IfaceEq)] -- decl names, equality conditions + -> OccSet -- set of things that have changed +computeChangedOccs ver_fn this_module old_usages eq_info = foldl add_changes emptyOccSet (stronglyConnComp edges) where - edges :: [((OccName,IfaceEq), Unique, [Unique])] + + -- return True if an external name has changed + name_changed :: Name -> Bool + name_changed nm + | Just ents <- lookupUFM usg_modmap (moduleName mod) + = case lookupUFM ents parent_occ of + Nothing -> pprPanic "computeChangedOccs" (ppr nm) + Just v -> v < new_version + | otherwise = False -- must be in another package + where + mod = nameModule nm + (parent_occ, new_version) = ver_fn nm + + -- Turn the usages from the old ModIface into a mapping + usg_modmap = listToUFM [ (usg_mod usg, listToUFM (usg_entities usg)) + | usg <- old_usages ] + + get_local_eq_info :: GenIfaceEq NameSet -> GenIfaceEq OccSet + get_local_eq_info Equal = Equal + get_local_eq_info NotEqual = NotEqual + get_local_eq_info (EqBut ns) = foldNameSet f Equal ns + where f name eq | nameModule name == this_module = + EqBut (unitOccSet (nameOccName name)) `and_occifeq` eq + | name_changed name = NotEqual + | otherwise = eq + + local_eq_infos = mapSnd get_local_eq_info eq_info + + edges :: [((OccName, OccIfaceEq), Unique, [Unique])] edges = [ (node, getUnique occ, map getUnique occs) - | node@(occ, iface_eq) <- eq_info + | node@(occ, iface_eq) <- local_eq_infos , let occs = case iface_eq of EqBut occ_set -> occSetElts occ_set other -> [] ] -- Changes in declarations - add_changes :: OccSet -> SCC (OccName, IfaceEq) -> OccSet + add_changes :: OccSet -> SCC (OccName, OccIfaceEq) -> OccSet add_changes so_far (AcyclicSCC (occ, iface_eq)) - | changedWrt so_far iface_eq -- This one has changed + | changedWrt so_far iface_eq -- This one has changed = extendOccSet so_far occ add_changes so_far (CyclicSCC pairs) - | changedWrt so_far (foldr1 (&&&) (map snd pairs)) -- One of this group has changed - = extendOccSetList so_far (map fst pairs) + | changedWrt so_far (foldr1 and_occifeq iface_eqs) + -- One of this group has changed + = extendOccSetList so_far occs + where (occs, iface_eqs) = unzip pairs add_changes so_far other = so_far -changedWrt :: OccSet -> IfaceEq -> Bool +type OccIfaceEq = GenIfaceEq OccSet + +changedWrt :: OccSet -> OccIfaceEq -> Bool changedWrt so_far Equal = False changedWrt so_far NotEqual = True changedWrt so_far (EqBut kids) = so_far `intersectsOccSet` kids +changedWrtNames :: OccSet -> IfaceEq -> Bool +changedWrtNames so_far Equal = False +changedWrtNames so_far NotEqual = True +changedWrtNames so_far (EqBut kids) = + so_far `intersectsOccSet` mkOccSet (map nameOccName (nameSetToList kids)) + +and_occifeq :: OccIfaceEq -> OccIfaceEq -> OccIfaceEq +Equal `and_occifeq` x = x +NotEqual `and_occifeq` x = NotEqual +EqBut nms `and_occifeq` Equal = EqBut nms +EqBut nms `and_occifeq` NotEqual = NotEqual +EqBut nms1 `and_occifeq` EqBut nms2 = EqBut (nms1 `unionOccSets` nms2) + ---------------------- -- mkOrphMap partitions instance decls or rules into -- (a) an OccEnv for ones that are not orphans, @@ -672,28 +714,25 @@ mkUsageInfo hsc_env dir_imp_mods dep_mods used_names -- don't get evaluated for a while and we can end up hanging on to -- the entire collection of Ifaces. -mk_usage_info pit hsc_env dir_imp_mods dep_mods proto_used_names +mk_usage_info pit hsc_env dir_imp_mods dep_mods used_names = mapCatMaybes mkUsage dep_mods -- ToDo: do we need to sort into canonical order? where hpt = hsc_HPT hsc_env dflags = hsc_dflags hsc_env - used_names = mkNameSet $ -- Eliminate duplicates - [ nameParent n -- Just record usage on the 'main' names - | n <- nameSetToList proto_used_names - , not (isWiredInName n) -- Don't record usages for wired-in names - , isExternalName n -- Ignore internal names - ] - -- ent_map groups together all the things imported and used -- from a particular module in this package ent_map :: ModuleEnv [OccName] ent_map = foldNameSet add_mv emptyModuleEnv used_names - add_mv name mv_map = extendModuleEnv_C add_item mv_map mod [occ] + add_mv name mv_map + | isWiredInName name = mv_map -- ignore wired-in names + | otherwise + = case nameModule_maybe name of + Nothing -> mv_map -- ignore internal names + Just mod -> extendModuleEnv_C add_item mv_map mod [occ] where occ = nameOccName name - mod = nameModule name add_item occs _ = occ:occs depend_on_exports mod = case lookupModuleEnv dir_imp_mods mod of @@ -718,7 +757,7 @@ mk_usage_info pit hsc_env dir_imp_mods dep_mods proto_used_names = Just (Usage { usg_name = mod_name, usg_mod = mod_vers, usg_exports = export_vers, - usg_entities = ent_vers, + usg_entities = fmToList ent_vers, usg_rules = rules_vers }) where maybe_iface = lookupIfaceByModule dflags hpt pit mod @@ -735,40 +774,48 @@ mk_usage_info pit hsc_env dir_imp_mods dep_mods proto_used_names export_vers | depend_on_exports mod = Just (mi_exp_vers iface) | otherwise = Nothing - -- The sort is to put them into canonical order used_occs = lookupModuleEnv ent_map mod `orElse` [] - ent_vers :: [(OccName,Version)] - ent_vers = [ (occ, version_env occ `orElse` initialVersion) - | occ <- sortLe (<=) used_occs] + + -- Making a FiniteMap here ensures that (a) we remove duplicates + -- when we have usages on several subordinates of a single parent, + -- and (b) that the usages emerge in a canonical order, which + -- is why we use FiniteMap rather than OccEnv: FiniteMap works + -- using Ord on the OccNames, which is a lexicographic ordering. + ent_vers :: FiniteMap OccName Version + ent_vers = listToFM (map lookup_occ used_occs) + + lookup_occ occ = + case version_env occ of + Nothing -> pprTrace "hmm, strange" (ppr mod <+> ppr occ) $ + (occ, initialVersion) -- does this ever happen? + Just (parent, version) -> (parent, version) \end{code} \begin{code} -mkIfaceExports :: NameSet -> [(Module, [GenAvailInfo OccName])] +mkIfaceExports :: [AvailInfo] + -> [(Module, [GenAvailInfo OccName])] -- Group by module and sort by occurrence -- This keeps the list in canonical order -mkIfaceExports exports - = [ (mod, eltsUFM avails) +mkIfaceExports exports + = [ (mod, eltsFM avails) | (mod, avails) <- fmToList groupFM ] where - groupFM :: ModuleEnv (UniqFM (GenAvailInfo OccName)) - -- Deliberately use the FastString so we + -- Deliberately use FiniteMap rather than UniqFM so we -- get a canonical ordering - groupFM = foldl add emptyModuleEnv (nameSetToList exports) + groupFM :: ModuleEnv (FiniteMap FastString (GenAvailInfo OccName)) + groupFM = foldl add emptyModuleEnv exports - add env name = extendModuleEnv_C add_avail env mod - (unitUFM avail_fs avail) + add env avail + = extendModuleEnv_C add_avail env mod (unitFM avail_fs avail_occ) where - occ = nameOccName name - mod = nameModule name - avail | Just p <- nameParent_maybe name = AvailTC (nameOccName p) [occ] - | isTcOcc occ = AvailTC occ [occ] - | otherwise = Avail occ - avail_fs = occNameFS (availName avail) - add_avail avail_fm _ = addToUFM_C add_item avail_fm avail_fs avail - - add_item (AvailTC p occs) _ = AvailTC p (List.insert occ occs) - add_item (Avail n) _ = pprPanic "MkIface.addAvail" (ppr n <+> ppr name) + avail_occ = availToOccs avail + mod = nameModule (availName avail) + avail_fs = occNameFS (availName avail_occ) + add_avail avail_fm _ = addToFM avail_fm avail_fs avail_occ + + availToOccs (Avail n) = Avail (nameOccName n) + availToOccs (AvailTC tc ns) = AvailTC (nameOccName tc) (map nameOccName ns) \end{code} @@ -961,7 +1008,7 @@ checkEntityUsage new_vers (name,old_vers) Nothing -> -- We used it before, but it ain't there now out_of_date (sep [ptext SLIT("No longer exported:"), ppr name]) - Just new_vers -- It's there, but is it up to date? + Just (_, new_vers) -- It's there, but is it up to date? | new_vers == old_vers -> traceHiDiffs (text " Up to date" <+> ppr name <+> parens (ppr new_vers)) `thenM_` returnM upToDate | otherwise -> out_of_date_vers (ptext SLIT(" Out of date:") <+> ppr name) @@ -990,26 +1037,26 @@ checkList (check:checks) = check `thenM` \ recompile -> %************************************************************************ \begin{code} -tyThingToIfaceDecl :: (Name -> IfaceExtName) -> TyThing -> IfaceDecl +tyThingToIfaceDecl :: 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), +tyThingToIfaceDecl (AnId id) + = IfaceId { ifName = getOccName id, + ifType = toIfaceType (idType id), ifIdInfo = info } where - info = case toIfaceIdInfo ext (idInfo id) of + info = case toIfaceIdInfo (idInfo id) of [] -> NoInfo items -> HasInfo items -tyThingToIfaceDecl ext (AClass clas) - = IfaceClass { ifCtxt = toIfaceContext ext sc_theta, +tyThingToIfaceDecl (AClass clas) + = IfaceClass { ifCtxt = toIfaceContext sc_theta, ifName = getOccName clas, ifTyVars = toIfaceTvBndrs clas_tyvars, ifFDs = map toIfaceFD clas_fds, - ifATs = map (tyThingToIfaceDecl ext . ATyCon) clas_ats, + ifATs = map (tyThingToIfaceDecl . ATyCon) clas_ats, ifSigs = map toIfaceClassOp op_stuff, ifRec = boolToRecFlag (isRecursiveTyCon tycon) } where @@ -1019,7 +1066,7 @@ tyThingToIfaceDecl ext (AClass clas) toIfaceClassOp (sel_id, def_meth) = ASSERT(sel_tyvars == clas_tyvars) - IfaceClassOp (getOccName sel_id) def_meth (toIfaceType ext op_ty) + IfaceClassOp (getOccName sel_id) def_meth (toIfaceType op_ty) where -- Be careful when splitting the type, because of things -- like class Foo a where @@ -1029,19 +1076,19 @@ tyThingToIfaceDecl ext (AClass clas) (sel_tyvars, rho_ty) = splitForAllTys (idType sel_id) op_ty = funResultTy rho_ty - toIfaceFD (tvs1, tvs2) = (map (occNameFS.getOccName) tvs1, map (occNameFS.getOccName) tvs2) + toIfaceFD (tvs1, tvs2) = (map getFS tvs1, map getFS tvs2) -tyThingToIfaceDecl ext (ATyCon tycon) +tyThingToIfaceDecl (ATyCon tycon) | isSynTyCon tycon - = IfaceSyn { ifName = getOccName tycon, - ifTyVars = toIfaceTvBndrs tyvars, + = IfaceSyn { ifName = getOccName tycon, + ifTyVars = toIfaceTvBndrs tyvars, ifOpenSyn = syn_isOpen, - ifSynRhs = toIfaceType ext syn_tyki } + ifSynRhs = toIfaceType syn_tyki } | isAlgTyCon tycon = IfaceData { ifName = getOccName tycon, ifTyVars = toIfaceTvBndrs tyvars, - ifCtxt = toIfaceContext ext (tyConStupidTheta tycon), + ifCtxt = toIfaceContext (tyConStupidTheta tycon), ifCons = ifaceConDecls (algTyConRhs tycon), ifRec = boolToRecFlag (isRecursiveTyCon tycon), ifGadtSyntax = isGadtSyntaxTyCon tycon, @@ -1088,51 +1135,52 @@ tyThingToIfaceDecl ext (ATyCon tycon) ifConUnivTvs = toIfaceTvBndrs (dataConUnivTyVars data_con), ifConExTvs = toIfaceTvBndrs (dataConExTyVars data_con), ifConEqSpec = to_eq_spec (dataConEqSpec data_con), - ifConCtxt = toIfaceContext ext (dataConTheta data_con), - ifConArgTys = map (toIfaceType ext) - (dataConOrigArgTys data_con), + ifConCtxt = toIfaceContext (dataConTheta data_con), + ifConArgTys = map toIfaceType (dataConOrigArgTys data_con), ifConFields = map getOccName (dataConFieldLabels data_con), ifConStricts = dataConStrictMarks data_con } - to_eq_spec spec = [(getOccName tv, toIfaceType ext ty) | (tv,ty) <- spec] + to_eq_spec spec = [(getOccName tv, toIfaceType ty) | (tv,ty) <- spec] famInstToIface Nothing = Nothing famInstToIface (Just (famTyCon, instTys)) = - Just (toIfaceTyCon ext famTyCon, map (toIfaceType ext) instTys) + Just (toIfaceTyCon famTyCon, map toIfaceType instTys) -tyThingToIfaceDecl ext (ADataCon dc) +tyThingToIfaceDecl (ADataCon dc) = pprPanic "toIfaceDecl" (ppr dc) -- Should be trimmed out earlier +getFS x = occNameFS (getOccName x) + -------------------------- -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, +instanceToIfaceInst :: Instance -> IfaceInst +instanceToIfaceInst ispec@(Instance { is_dfun = dfun_id, is_flag = oflag, + is_cls = cls, is_tcs = mb_tcs, + is_orph = orph }) + = IfaceInst { ifDFun = getName dfun_id, ifOFlag = oflag, - ifInstCls = ext_lhs cls, + ifInstCls = cls, ifInstTys = map do_rough mb_tcs, ifInstOrph = orph } where do_rough Nothing = Nothing - do_rough (Just n) = Just (toIfaceTyCon_name ext_lhs n) + do_rough (Just n) = Just (toIfaceTyCon_name n) -------------------------- -famInstToIfaceFamInst :: (Name -> IfaceExtName) -> FamInst -> IfaceFamInst -famInstToIfaceFamInst ext_lhs fi@(FamInst { fi_tycon = tycon, +famInstToIfaceFamInst :: FamInst -> IfaceFamInst +famInstToIfaceFamInst fi@(FamInst { fi_tycon = tycon, fi_fam = fam, fi_tcs = mb_tcs }) - = IfaceFamInst { ifFamInstTyCon = toIfaceTyCon ext_lhs tycon - , ifFamInstFam = ext_lhs fam + = IfaceFamInst { ifFamInstTyCon = toIfaceTyCon tycon + , ifFamInstFam = fam , ifFamInstTys = map do_rough mb_tcs } where do_rough Nothing = Nothing - do_rough (Just n) = Just (toIfaceTyCon_name ext_lhs n) + do_rough (Just n) = Just (toIfaceTyCon_name n) -------------------------- -toIfaceIdInfo :: (Name -> IfaceExtName) -> IdInfo -> [IfaceInfoItem] -toIfaceIdInfo ext id_info +toIfaceIdInfo :: IdInfo -> [IfaceInfoItem] +toIfaceIdInfo id_info = catMaybes [arity_hsinfo, caf_hsinfo, strict_hsinfo, inline_hsinfo, wrkr_hsinfo, unfold_hsinfo] where @@ -1158,7 +1206,7 @@ toIfaceIdInfo ext 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) + Just (HsWorker ((idName work_id)) wrap_arity) NoWorker -> Nothing ------------ Unfolding -------------- @@ -1171,7 +1219,7 @@ toIfaceIdInfo ext id_info -- unconditional NOINLINE, etc. See TidyPgm.addExternal unfold_hsinfo | no_unfolding = Nothing | has_worker = Nothing -- Unfolding is implicit - | otherwise = Just (HsUnfold (toIfaceExpr ext rhs)) + | otherwise = Just (HsUnfold (toIfaceExpr rhs)) ------------ Inline prag -------------- inline_prag = inlinePragInfo id_info @@ -1182,63 +1230,61 @@ toIfaceIdInfo ext id_info | otherwise = Just (HsInline inline_prag) -------------------------- -coreRuleToIfaceRule :: (Name -> IfaceExtName) -- For the LHS names - -> (Name -> IfaceExtName) -- For the RHS names - -> CoreRule -> IfaceRule -coreRuleToIfaceRule ext_lhs ext_rhs (BuiltinRule { ru_fn = fn}) +coreRuleToIfaceRule :: CoreRule -> IfaceRule +coreRuleToIfaceRule (BuiltinRule { ru_fn = fn}) = pprTrace "toHsRule: builtin" (ppr fn) $ - bogusIfaceRule (mkIfaceExtName fn) + bogusIfaceRule 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 }) +coreRuleToIfaceRule (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, + ifRuleBndrs = map toIfaceBndr bndrs, + ifRuleHead = fn, ifRuleArgs = map do_arg args, - ifRuleRhs = toIfaceExpr ext_rhs rhs, + ifRuleRhs = toIfaceExpr 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 + do_arg (Type ty) = IfaceType (toIfaceType (deNoteType ty)) + do_arg arg = toIfaceExpr arg -bogusIfaceRule :: IfaceExtName -> IfaceRule +bogusIfaceRule :: Name -> 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] -toIfaceExpr ext (Case s x ty as) = IfaceCase (toIfaceExpr ext s) (occNameFS (getOccName x)) (toIfaceType ext ty) (map (toIfaceAlt ext) as) -toIfaceExpr ext (Let b e) = IfaceLet (toIfaceBind ext b) (toIfaceExpr ext e) -toIfaceExpr ext (Cast e co) = IfaceCast (toIfaceExpr ext e) (toIfaceType ext co) -toIfaceExpr ext (Note n e) = IfaceNote (toIfaceNote ext n) (toIfaceExpr ext e) +toIfaceExpr :: CoreExpr -> IfaceExpr +toIfaceExpr (Var v) = toIfaceVar v +toIfaceExpr (Lit l) = IfaceLit l +toIfaceExpr (Type ty) = IfaceType (toIfaceType ty) +toIfaceExpr (Lam x b) = IfaceLam (toIfaceBndr x) (toIfaceExpr b) +toIfaceExpr (App f a) = toIfaceApp f [a] +toIfaceExpr (Case s x ty as) = IfaceCase (toIfaceExpr s) (getFS x) (toIfaceType ty) (map toIfaceAlt as) +toIfaceExpr (Let b e) = IfaceLet (toIfaceBind b) (toIfaceExpr e) +toIfaceExpr (Cast e co) = IfaceCast (toIfaceExpr e) (toIfaceType co) +toIfaceExpr (Note n e) = IfaceNote (toIfaceNote n) (toIfaceExpr e) --------------------- -toIfaceNote ext (SCC cc) = IfaceSCC cc -toIfaceNote ext InlineMe = IfaceInlineMe -toIfaceNote ext (CoreNote s) = IfaceCoreNote s +toIfaceNote (SCC cc) = IfaceSCC cc +toIfaceNote InlineMe = IfaceInlineMe +toIfaceNote (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] +toIfaceBind (NonRec b r) = IfaceNonRec (toIfaceIdBndr b) (toIfaceExpr r) +toIfaceBind (Rec prs) = IfaceRec [(toIfaceIdBndr b, toIfaceExpr r) | (b,r) <- prs] --------------------- -toIfaceAlt ext (c,bs,r) = (toIfaceCon c, map (occNameFS.getOccName) bs, toIfaceExpr ext r) +toIfaceAlt (c,bs,r) = (toIfaceCon c, map getFS bs, toIfaceExpr r) --------------------- toIfaceCon (DataAlt dc) | isTupleTyCon tc = IfaceTupleAlt (tupleTyConBoxity tc) - | otherwise = IfaceDataAlt (getOccName dc) + | otherwise = IfaceDataAlt (getName dc) where tc = dataConTyCon dc @@ -1246,8 +1292,8 @@ toIfaceCon (LitAlt l) = IfaceLitAlt l toIfaceCon DEFAULT = IfaceDefault --------------------- -toIfaceApp ext (App f a) as = toIfaceApp ext f (a:as) -toIfaceApp ext (Var v) as +toIfaceApp (App f a) as = toIfaceApp f (a:as) +toIfaceApp (Var v) as = case isDataConWorkId_maybe v of -- We convert the *worker* for tuples into IfaceTuples Just dc | isTupleTyCon tc && saturated @@ -1255,22 +1301,22 @@ toIfaceApp ext (Var v) as where val_args = dropWhile isTypeArg as saturated = val_args `lengthIs` idArity v - tup_args = map (toIfaceExpr ext) val_args + tup_args = map toIfaceExpr val_args tc = dataConTyCon dc - other -> mkIfaceApps ext (toIfaceVar ext v) as + other -> mkIfaceApps (toIfaceVar v) as -toIfaceApp ext e as = mkIfaceApps ext (toIfaceExpr ext e) as +toIfaceApp e as = mkIfaceApps (toIfaceExpr e) as -mkIfaceApps ext f as = foldl (\f a -> IfaceApp f (toIfaceExpr ext a)) f as +mkIfaceApps f as = foldl (\f a -> IfaceApp f (toIfaceExpr a)) f as --------------------- -toIfaceVar :: (Name -> IfaceExtName) -> Id -> IfaceExpr -toIfaceVar ext v - | Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType ext (idType v)) +toIfaceVar :: Id -> IfaceExpr +toIfaceVar v + | Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType (idType v)) -- Foreign calls have special syntax - | isExternalName name = IfaceExt (ext name) - | otherwise = IfaceLcl (occNameFS (nameOccName name)) + | isExternalName name = IfaceExt name + | otherwise = IfaceLcl (getFS name) where name = idName v \end{code} diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs index fa227e6756..c16846ec28 100644 --- a/compiler/iface/TcIface.lhs +++ b/compiler/iface/TcIface.lhs @@ -14,9 +14,9 @@ module TcIface ( import IfaceSyn import LoadIface ( loadInterface, loadWiredInHomeIface, findAndReadIface, loadDecls ) -import IfaceEnv ( lookupIfaceTop, lookupIfaceExt, newGlobalBinder, +import IfaceEnv ( lookupIfaceTop, newGlobalBinder, extendIfaceIdEnv, extendIfaceTyVarEnv, newIPName, - tcIfaceTyVar, tcIfaceLclId, lookupIfaceTc, + tcIfaceTyVar, tcIfaceLclId, newIfaceName, newIfaceNames, ifaceExportNames ) import BuildTyCl ( buildSynTyCon, buildAlgTyCon, buildDataCon, buildClass, @@ -511,10 +511,9 @@ tcIfaceInst (IfaceInst { ifDFun = dfun_occ, ifOFlag = oflag, ifInstCls = cls, ifInstTys = mb_tcs, ifInstOrph = orph }) = do { dfun <- forkM (ptext SLIT("Dict fun") <+> ppr dfun_occ) $ - tcIfaceExtId (LocalTop dfun_occ) - ; cls' <- lookupIfaceExt cls - ; mb_tcs' <- mapM tc_rough mb_tcs - ; return (mkImportedInstance cls' mb_tcs' orph dfun oflag) } + tcIfaceExtId dfun_occ + ; let mb_tcs' = map (fmap ifaceTyConName) mb_tcs + ; return (mkImportedInstance cls mb_tcs' orph dfun oflag) } tcIfaceFamInst :: IfaceFamInst -> IfL FamInst tcIfaceFamInst (IfaceFamInst { ifFamInstTyCon = tycon, @@ -523,12 +522,8 @@ tcIfaceFamInst (IfaceFamInst { ifFamInstTyCon = tycon, -- ^^^this line doesn't work, but vvv this does => CPP in Haskell = evil! = do { tycon' <- forkM (text ("Inst tycon") <+> ppr tycon) $ tcIfaceTyCon tycon - ; fam' <- lookupIfaceExt fam - ; mb_tcs' <- mapM tc_rough mb_tcs - ; return (mkImportedFamInst fam' mb_tcs' tycon') } - -tc_rough Nothing = return Nothing -tc_rough (Just tc) = do { tc' <- lookupIfaceTc tc; return (Just tc') } + ; let mb_tcs' = map (fmap ifaceTyConName) mb_tcs + ; return (mkImportedFamInst fam mb_tcs' tycon') } \end{code} @@ -554,20 +549,21 @@ tcIfaceRule :: IfaceRule -> IfL CoreRule tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs, ifRuleHead = fn, ifRuleArgs = args, ifRuleRhs = rhs, ifRuleOrph = orph }) - = do { fn' <- lookupIfaceExt fn - ; ~(bndrs', args', rhs') <- + = do { ~(bndrs', args', rhs') <- -- Typecheck the payload lazily, in the hope it'll never be looked at forkM (ptext SLIT("Rule") <+> ftext name) $ bindIfaceBndrs bndrs $ \ bndrs' -> do { args' <- mappM tcIfaceExpr args ; rhs' <- tcIfaceExpr rhs ; return (bndrs', args', rhs') } - ; mb_tcs <- mapM ifTopFreeName args - ; returnM (Rule { ru_name = name, ru_fn = fn', ru_act = act, + ; let mb_tcs = map ifTopFreeName args + ; lcl <- getLclEnv + ; let this_module = if_mod lcl + ; returnM (Rule { ru_name = name, ru_fn = fn, ru_act = act, ru_bndrs = bndrs', ru_args = args', ru_rhs = rhs', ru_orph = orph, ru_rough = mb_tcs, - ru_local = isLocalIfaceExtName fn }) } + ru_local = nameModule fn == this_module }) } where -- This function *must* mirror exactly what Rules.topFreeName does -- We could have stored the ru_rough field in the iface file @@ -576,14 +572,11 @@ tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bnd -- type syononyms at the top of a type arg. Since -- we can't tell at this point, we are careful not -- to write them out in coreRuleToIfaceRule - ifTopFreeName :: IfaceExpr -> IfL (Maybe Name) - ifTopFreeName (IfaceType (IfaceTyConApp tc _ )) - = do { n <- lookupIfaceTc tc - ; return (Just n) } - ifTopFreeName (IfaceApp f a) = ifTopFreeName f - ifTopFreeName (IfaceExt ext) = do { n <- lookupIfaceExt ext - ; return (Just n) } - ifTopFreeName other = return Nothing + ifTopFreeName :: IfaceExpr -> Maybe Name + ifTopFreeName (IfaceType (IfaceTyConApp tc _ )) = Just (ifaceTyConName tc) + ifTopFreeName (IfaceApp f a) = ifTopFreeName f + ifTopFreeName (IfaceExt n) = Just n + ifTopFreeName other = Nothing \end{code} @@ -725,8 +718,7 @@ tcIfaceAlt _ (IfaceLitAlt lit, names, rhs) -- by the fact that we omit type annotations because we can -- work them out. True enough, but its not that easy! tcIfaceAlt (tycon, inst_tys) (IfaceDataAlt data_occ, arg_strs, rhs) - = do { let tycon_mod = nameModule (tyConName tycon) - ; con <- tcIfaceDataCon (ExtPkg tycon_mod data_occ) + = do { con <- tcIfaceDataCon data_occ ; ASSERT2( con `elem` tyConDataCons tycon, ppr con $$ ppr tycon $$ ppr (tyConDataCons tycon) ) tcIfaceDataAlt con inst_tys arg_strs rhs } @@ -931,12 +923,11 @@ tcIfaceTyCon IfaceCharTc = tcWiredInTyCon charTyCon tcIfaceTyCon IfaceListTc = tcWiredInTyCon listTyCon tcIfaceTyCon IfacePArrTc = tcWiredInTyCon parrTyCon tcIfaceTyCon (IfaceTupTc bx ar) = tcWiredInTyCon (tupleTyCon bx ar) -tcIfaceTyCon (IfaceTc ext_nm) = do { name <- lookupIfaceExt ext_nm - ; thing <- tcIfaceGlobal name +tcIfaceTyCon (IfaceTc name) = do { thing <- tcIfaceGlobal name ; return (check_tc (tyThingTyCon thing)) } where #ifdef DEBUG - check_tc tc = case toIfaceTyCon (error "urk") tc of + check_tc tc = case toIfaceTyCon tc of IfaceTc _ -> tc other -> pprTrace "check_tc" (ppr tc) tc #else @@ -956,24 +947,21 @@ tcWiredInTyCon :: TyCon -> IfL TyCon tcWiredInTyCon tc = do { ifCheckWiredInThing (tyConName tc) ; return tc } -tcIfaceClass :: IfaceExtName -> IfL Class -tcIfaceClass rdr_name = do { name <- lookupIfaceExt rdr_name - ; thing <- tcIfaceGlobal name - ; return (tyThingClass thing) } +tcIfaceClass :: Name -> IfL Class +tcIfaceClass name = do { thing <- tcIfaceGlobal name + ; return (tyThingClass thing) } -tcIfaceDataCon :: IfaceExtName -> IfL DataCon -tcIfaceDataCon gbl = do { name <- lookupIfaceExt gbl - ; thing <- tcIfaceGlobal name - ; case thing of +tcIfaceDataCon :: Name -> IfL DataCon +tcIfaceDataCon name = do { thing <- tcIfaceGlobal name + ; case thing of ADataCon dc -> return dc - other -> pprPanic "tcIfaceExtDC" (ppr gbl $$ ppr name$$ ppr thing) } + other -> pprPanic "tcIfaceExtDC" (ppr name$$ ppr thing) } -tcIfaceExtId :: IfaceExtName -> IfL Id -tcIfaceExtId gbl = do { name <- lookupIfaceExt gbl - ; thing <- tcIfaceGlobal name - ; case thing of +tcIfaceExtId :: Name -> IfL Id +tcIfaceExtId name = do { thing <- tcIfaceGlobal name + ; case thing of AnId id -> return id - other -> pprPanic "tcIfaceExtId" (ppr gbl $$ ppr name$$ ppr thing) } + other -> pprPanic "tcIfaceExtId" (ppr name$$ ppr thing) } \end{code} %************************************************************************ @@ -1018,7 +1006,7 @@ bindIfaceIds bndrs thing_inside newExtCoreBndr :: IfaceIdBndr -> IfL Id newExtCoreBndr (var, ty) = do { mod <- getIfModule - ; name <- newGlobalBinder mod (mkVarOccFS var) Nothing noSrcLoc + ; name <- newGlobalBinder mod (mkVarOccFS var) noSrcLoc ; ty' <- tcIfaceType ty ; return (mkLocalId name ty') } |