diff options
author | Simon Marlow <simonmar@microsoft.com> | 2006-07-25 13:01:54 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2006-07-25 13:01:54 +0000 |
commit | 61d2625ae2e6a4cdae2ffc92df828905e81c24cc (patch) | |
tree | 9577057d0ba03d38aca3431090fb6d6f491ab3f1 /compiler/iface | |
parent | b93eb0c23bed01905e86c0a8c485edb388626761 (diff) | |
download | haskell-61d2625ae2e6a4cdae2ffc92df828905e81c24cc.tar.gz |
Generalise Package Support
This patch pushes through one fundamental change: a module is now
identified by the pair of its package and module name, whereas
previously it was identified by its module name alone. This means
that now a program can contain multiple modules with the same name, as
long as they belong to different packages.
This is a language change - the Haskell report says nothing about
packages, but it is now necessary to understand packages in order to
understand GHC's module system. For example, a type T from module M
in package P is different from a type T from module M in package Q.
Previously this wasn't an issue because there could only be a single
module M in the program.
The "module restriction" on combining packages has therefore been
lifted, and a program can contain multiple versions of the same
package.
Note that none of the proposed syntax changes have yet been
implemented, but the architecture is geared towards supporting import
declarations qualified by package name, and that is probably the next
step.
It is now necessary to specify the package name when compiling a
package, using the -package-name flag (which has been un-deprecated).
Fortunately Cabal still uses -package-name.
Certain packages are "wired in". Currently the wired-in packages are:
base, haskell98, template-haskell and rts, and are always referred to
by these versionless names. Other packages are referred to with full
package IDs (eg. "network-1.0"). This is because the compiler needs
to refer to entities in the wired-in packages, and we didn't want to
bake the version of these packages into the comiler. It's conceivable
that someone might want to upgrade the base package independently of
GHC.
Internal changes:
- There are two module-related types:
ModuleName just a FastString, the name of a module
Module a pair of a PackageId and ModuleName
A mapping from ModuleName can be a UniqFM, but a mapping from Module
must be a FiniteMap (we provide it as ModuleEnv).
- The "HomeModules" type that was passed around the compiler is now
gone, replaced in most cases by the current package name which is
contained in DynFlags. We can tell whether a Module comes from the
current package by comparing its package name against the current
package.
- While I was here, I changed PrintUnqual to be a little more useful:
it now returns the ModuleName that the identifier should be qualified
with according to the current scope, rather than its original
module. Also, PrintUnqual tells whether to qualify module names with
package names (currently unused).
Docs to follow.
Diffstat (limited to 'compiler/iface')
-rw-r--r-- | compiler/iface/BinIface.hs | 3 | ||||
-rw-r--r-- | compiler/iface/IfaceEnv.lhs | 16 | ||||
-rw-r--r-- | compiler/iface/IfaceType.lhs | 33 | ||||
-rw-r--r-- | compiler/iface/LoadIface.lhs | 157 | ||||
-rw-r--r-- | compiler/iface/MkIface.lhs | 110 | ||||
-rw-r--r-- | compiler/iface/TcIface.lhs | 13 |
6 files changed, 161 insertions, 171 deletions
diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs index 631a28660e..6af109c6f0 100644 --- a/compiler/iface/BinIface.hs +++ b/compiler/iface/BinIface.hs @@ -15,7 +15,6 @@ import NewDemand import IfaceSyn import VarEnv import InstEnv ( OverlapFlag(..) ) -import Packages ( PackageIdH(..) ) import Class ( DefMeth(..) ) import CostCentre import StaticFlags ( opt_HiVersion, v_Build_tag ) @@ -97,7 +96,6 @@ instance Binary ModIface where mi_module = mod, mi_boot = is_boot, mi_mod_vers = mod_vers, - mi_package = _, -- we ignore the package on output mi_orphan = orphan, mi_deps = deps, mi_usages = usages, @@ -162,7 +160,6 @@ instance Binary ModIface where rules <- {-# SCC "bin_rules" #-} lazyGet bh rule_vers <- get bh return (ModIface { - mi_package = HomePackage, -- to be filled in properly later mi_module = mod_name, mi_boot = is_boot, mi_mod_vers = mod_vers, diff --git a/compiler/iface/IfaceEnv.lhs b/compiler/iface/IfaceEnv.lhs index c7e78b3d45..3eceaa0f04 100644 --- a/compiler/iface/IfaceEnv.lhs +++ b/compiler/iface/IfaceEnv.lhs @@ -35,9 +35,9 @@ import Name ( Name, nameUnique, nameModule, import NameSet ( NameSet, emptyNameSet, addListToNameSet ) import OccName ( OccName, isTupleOcc_maybe, tcName, dataName, mapOccEnv, occNameFS, lookupOccEnv, unitOccEnv, extendOccEnv, extendOccEnvList ) -import PrelNames ( gHC_PRIM, pREL_TUP ) -import Module ( Module, emptyModuleEnv, - lookupModuleEnv, extendModuleEnv_C ) +import PrelNames ( gHC_PRIM, dATA_TUP ) +import Module ( Module, emptyModuleEnv, ModuleName, modulePackageId, + lookupModuleEnv, extendModuleEnv_C, mkModule ) import UniqFM ( lookupUFM, addListToUFM ) import FastString ( FastString ) import UniqSupply ( UniqSupply, splitUniqSupply, uniqFromSupply, uniqsFromSupply ) @@ -230,7 +230,7 @@ newIPName occ_name_ip \begin{code} lookupOrigNameCache :: OrigNameCache -> Module -> OccName -> Maybe Name lookupOrigNameCache nc mod occ - | mod == pREL_TUP || mod == gHC_PRIM, -- Boxed tuples from one, + | mod == dATA_TUP || mod == gHC_PRIM, -- Boxed tuples from one, Just tup_info <- isTupleOcc_maybe occ -- unboxed from the other = -- Special case for tuples; there are too many -- of them to pre-populate the original-name cache @@ -340,7 +340,7 @@ lookupIfaceTc other_tc = return (ifaceTyConName other_tc) lookupIfaceExt :: IfaceExtName -> IfL Name lookupIfaceExt (ExtPkg mod occ) = lookupOrig mod occ -lookupIfaceExt (HomePkg mod occ _) = lookupOrig mod occ +lookupIfaceExt (HomePkg mod occ _) = lookupHomePackage mod occ lookupIfaceExt (LocalTop occ) = lookupIfaceTop occ lookupIfaceExt (LocalTopSub occ _) = lookupIfaceTop occ @@ -349,6 +349,12 @@ lookupIfaceTop :: OccName -> IfL Name lookupIfaceTop occ = do { env <- getLclEnv; lookupOrig (if_mod env) occ } +lookupHomePackage :: ModuleName -> OccName -> IfL Name +lookupHomePackage mod_name occ + = do { env <- getLclEnv; + ; let this_pkg = modulePackageId (if_mod env) + ; lookupOrig (mkModule this_pkg mod_name) occ } + newIfaceName :: OccName -> IfL Name newIfaceName occ = do { uniq <- newUnique diff --git a/compiler/iface/IfaceType.lhs b/compiler/iface/IfaceType.lhs index bf0f3831b4..a487489f3a 100644 --- a/compiler/iface/IfaceType.lhs +++ b/compiler/iface/IfaceType.lhs @@ -10,7 +10,7 @@ module IfaceType ( IfaceContext, IfaceBndr(..), IfaceTvBndr, IfaceIdBndr, IfaceExtName(..), mkIfaceExtName, isLocalIfaceExtName, - ifaceTyConName, interactiveExtNameFun, + ifaceTyConName, -- Conversion from Type -> IfaceType toIfaceType, toIfacePred, toIfaceContext, @@ -34,7 +34,7 @@ import TysWiredIn ( listTyConName, parrTyConName, tupleTyCon, intTyConName, char import OccName ( OccName, parenSymOcc, occNameFS ) import Name ( Name, getName, getOccName, nameModule, nameOccName, wiredInNameTyThing_maybe ) -import Module ( Module ) +import Module ( Module, ModuleName ) import BasicTypes ( IPName(..), Arity, Version, mapIPName, tupleParens, Boxity ) import Outputable import FastString @@ -49,13 +49,15 @@ import FastString \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 + = 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 Module OccName Version -- From another module in home package; - -- has version #; in all other respects, - -- HomePkg and ExtPkg are the same + | 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 @@ -79,14 +81,6 @@ ifaceExtOcc (ExtPkg _ occ) = occ ifaceExtOcc (HomePkg _ occ _) = occ ifaceExtOcc (LocalTop occ) = occ ifaceExtOcc (LocalTopSub occ _) = occ - -interactiveExtNameFun :: PrintUnqualified -> Name-> IfaceExtName -interactiveExtNameFun print_unqual name - | print_unqual mod occ = LocalTop occ - | otherwise = ExtPkg mod occ - where - mod = nameModule name - occ = nameOccName name \end{code} @@ -200,15 +194,12 @@ maybeParen ctxt_prec inner_prec pretty -- 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) = pprExt mod occ - ppr (HomePkg mod occ vers) = pprExt mod occ <> braces (ppr vers) + 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? - -pprExt :: Module -> OccName -> SDoc -- No need to worry about printing unqualified becuase that was handled -- in the transiation to IfaceSyn -pprExt mod occ = ppr mod <> dot <> ppr occ instance Outputable IfaceBndr where ppr (IfaceIdBndr bndr) = pprIfaceIdBndr bndr diff --git a/compiler/iface/LoadIface.lhs b/compiler/iface/LoadIface.lhs index 8c496f76ef..8bcf987c99 100644 --- a/compiler/iface/LoadIface.lhs +++ b/compiler/iface/LoadIface.lhs @@ -5,7 +5,7 @@ \begin{code} module LoadIface ( - loadInterface, loadHomeInterface, loadWiredInHomeIface, + loadInterface, loadInterfaceForName, loadWiredInHomeIface, loadSrcInterface, loadSysInterface, loadOrphanModules, findAndReadIface, readIface, -- Used when reading the module's old interface loadDecls, ifaceStats, discardDeclPrags, @@ -16,9 +16,7 @@ module LoadIface ( import {-# SOURCE #-} TcIface( tcIfaceDecl, tcIfaceRule, tcIfaceInst ) -import Packages ( PackageState(..), PackageIdH(..), isHomePackage ) -import DynFlags ( DynFlags(..), DynFlag( Opt_IgnoreInterfacePragmas ), - isOneShot ) +import DynFlags ( DynFlags(..), DynFlag( Opt_IgnoreInterfacePragmas ) ) import IfaceSyn ( IfaceDecl(..), IfaceConDecl(..), IfaceClassOp(..), IfaceConDecls(..), IfaceIdInfo(..) ) import IfaceEnv ( newGlobalBinder ) @@ -43,17 +41,15 @@ import Name ( Name {-instance NamedThing-}, getOccName, nameModule, nameIsLocalOrFrom, isWiredInName ) import NameEnv import MkId ( seqId ) -import Module ( Module, ModLocation(ml_hi_file), emptyModuleEnv, - addBootSuffix_maybe, - extendModuleEnv, lookupModuleEnv, moduleString - ) +import Module import OccName ( OccName, mkOccEnv, lookupOccEnv, mkClassTyConOcc, mkClassDataConOcc, mkSuperDictSelOcc, mkDataConWrapperOcc, mkDataConWorkerOcc ) import SrcLoc ( importedSrcLoc ) import Maybes ( MaybeErr(..) ) -import FastString ( mkFastString ) import ErrUtils ( Message ) -import Finder ( findModule, findPackageModule, FindResult(..), cantFindError ) +import Finder ( findImportedModule, findExactModule, + FindResult(..), cantFindError ) +import UniqFM import Outputable import BinIface ( readBinIface ) import Panic ( ghcError, tryMost, showException, GhcException(..) ) @@ -70,22 +66,31 @@ import List ( nub ) %************************************************************************ \begin{code} -loadSrcInterface :: SDoc -> Module -> IsBootInterface -> RnM ModIface --- This is called for each 'import' declaration in the source code --- On a failure, fail in the monad with an error message - -loadSrcInterface doc mod want_boot - = do { mb_iface <- initIfaceTcRn $ - loadInterface doc mod (ImportByUser want_boot) - ; case mb_iface of - Failed err -> failWithTc (elaborate err) - Succeeded iface -> return iface - } +-- | Load the interface corresponding to an @import@ directive in +-- source code. On a failure, fail in the monad with an error message. +loadSrcInterface :: SDoc -> ModuleName -> IsBootInterface -> RnM ModIface +loadSrcInterface doc mod want_boot = do + -- We must first find which Module this import refers to. This involves + -- calling the Finder, which as a side effect will search the filesystem + -- and create a ModLocation. If successful, loadIface will read the + -- interface; it will call the Finder again, but the ModLocation will be + -- cached from the first search. + hsc_env <- getTopEnv + res <- ioToIOEnv $ findImportedModule hsc_env mod Nothing + case res of + Found _ mod -> do + mb_iface <- initIfaceTcRn $ loadInterface doc mod (ImportByUser want_boot) + case mb_iface of + Failed err -> failWithTc (elaborate err) + Succeeded iface -> return iface + err -> + let dflags = hsc_dflags hsc_env in + failWithTc (elaborate (cantFindError dflags mod err)) where elaborate err = hang (ptext SLIT("Failed to load interface for") <+> quotes (ppr mod) <> colon) 4 err ---------------- +-- | Load interfaces for a collection of orphan modules. loadOrphanModules :: [Module] -> TcM () loadOrphanModules mods | null mods = returnM () @@ -98,9 +103,9 @@ loadOrphanModules mods load mod = loadSysInterface (mk_doc mod) mod mk_doc mod = ppr mod <+> ptext SLIT("is a orphan-instance module") ---------------- -loadHomeInterface :: SDoc -> Name -> TcRn ModIface -loadHomeInterface doc name +-- | Loads the interface for a given Name. +loadInterfaceForName :: SDoc -> Name -> TcRn ModIface +loadInterfaceForName doc name = do { #ifdef DEBUG -- Should not be called with a name from the module being compiled @@ -110,19 +115,17 @@ loadHomeInterface doc name initIfaceTcRn $ loadSysInterface doc (nameModule name) } ---------------- -loadWiredInHomeIface :: Name -> IfM lcl () --- A IfM function to load the home interface for a wired-in thing, +-- | An 'IfM' function to load the home interface for a wired-in thing, -- so that we're sure that we see its instance declarations and rules +loadWiredInHomeIface :: Name -> IfM lcl () loadWiredInHomeIface name = ASSERT( isWiredInName name ) - do { loadSysInterface doc (nameModule name); return () } + do loadSysInterface doc (nameModule name); return () where doc = ptext SLIT("Need home interface for wired-in thing") <+> ppr name ---------------- +-- | A wrapper for 'loadInterface' that throws an exception if it fails loadSysInterface :: SDoc -> Module -> IfM lcl ModIface --- A wrapper for loadInterface that Throws an exception if it fails loadSysInterface doc mod_name = do { mb_iface <- loadInterface doc mod_name ImportBySystem ; case mb_iface of @@ -142,7 +145,7 @@ loadSysInterface doc mod_name %********************************************************* \begin{code} -loadInterface :: SDoc -> Module -> WhereFrom +loadInterface :: SDoc -> Module -> WhereFrom -> IfM lcl (MaybeErr Message ModIface) -- If it can't find a suitable interface file, we @@ -161,7 +164,8 @@ loadInterface doc_str mod from ; traceIf (text "Considering whether to load" <+> ppr mod <+> ppr from) -- Check whether we have the interface already - ; case lookupIfaceByModule hpt (eps_PIT eps) mod of { + ; dflags <- getDOpts + ; case lookupIfaceByModule dflags hpt (eps_PIT eps) mod of { Just iface -> returnM (Succeeded iface) ; -- Already loaded -- The (src_imp == mi_boot iface) test checks that the already-loaded @@ -173,7 +177,7 @@ loadInterface doc_str mod from ImportByUser usr_boot -> usr_boot ImportBySystem -> sys_boot - ; mb_dep = lookupModuleEnv (eps_is_boot eps) mod + ; mb_dep = lookupUFM (eps_is_boot eps) (moduleName mod) ; sys_boot = case mb_dep of Just (_, is_boot) -> is_boot Nothing -> False @@ -181,13 +185,11 @@ loadInterface doc_str mod from } -- based on the dependencies in directly-imported modules -- READ THE MODULE IN - ; let explicit | ImportByUser _ <- from = True - | otherwise = False - ; read_result <- findAndReadIface explicit doc_str mod hi_boot_file + ; read_result <- findAndReadIface doc_str mod hi_boot_file ; dflags <- getDOpts ; case read_result of { Failed err -> do - { let fake_iface = emptyModIface HomePackage mod + { let fake_iface = emptyModIface mod ; updateEps_ $ \eps -> eps { eps_PIT = extendModuleEnv (eps_PIT eps) (mi_module fake_iface) fake_iface } @@ -198,9 +200,10 @@ loadInterface doc_str mod from -- Found and parsed! Succeeded (iface, file_path) -- Sanity check: - | ImportBySystem <- from, -- system-importing... - isHomePackage (mi_package iface), -- ...a home-package module - Nothing <- mb_dep -- ...that we know nothing about + | ImportBySystem <- from, -- system-importing... + modulePackageId (mi_module iface) == thisPackage dflags, + -- a home-package module... + Nothing <- mb_dep -- that we know nothing about -> returnM (Failed (badDepMsg mod)) | otherwise -> @@ -312,7 +315,7 @@ loadDecl ignore_prags mod (_version, decl) -- imported name, to fix the module correctly in the cache mk_new_bndr mod mb_parent occ = newGlobalBinder mod occ mb_parent - (importedSrcLoc (moduleString mod)) + (importedSrcLoc (showSDoc (pprModule mod))) doc = ptext SLIT("Declaration for") <+> ppr (ifName decl) @@ -383,8 +386,7 @@ ifaceDeclSubBndrs _other = [] %********************************************************* \begin{code} -findAndReadIface :: Bool -- True <=> explicit user import - -> SDoc -> Module +findAndReadIface :: SDoc -> Module -> IsBootInterface -- True <=> Look for a .hi-boot file -- False <=> Look for .hi file -> TcRnIf gbl lcl (MaybeErr Message (ModIface, FilePath)) @@ -394,74 +396,62 @@ findAndReadIface :: Bool -- True <=> explicit user import -- It *doesn't* add an error to the monad, because -- sometimes it's ok to fail... see notes with loadInterface -findAndReadIface explicit doc_str mod_name hi_boot_file +findAndReadIface doc_str mod hi_boot_file = do { traceIf (sep [hsep [ptext SLIT("Reading"), if hi_boot_file then ptext SLIT("[boot]") else empty, ptext SLIT("interface for"), - ppr mod_name <> semi], + ppr mod <> semi], nest 4 (ptext SLIT("reason:") <+> doc_str)]) -- Check for GHC.Prim, and return its static interface ; dflags <- getDOpts - ; let base_pkg = basePackageId (pkgState dflags) - ; if mod_name == gHC_PRIM - then returnM (Succeeded (ghcPrimIface{ mi_package = base_pkg }, - "<built in interface for GHC.Prim>")) + ; if mod == gHC_PRIM + then returnM (Succeeded (ghcPrimIface, + "<built in interface for GHC.Prim>")) else do -- Look for the file ; hsc_env <- getTopEnv - ; mb_found <- ioToIOEnv (findHiFile hsc_env explicit mod_name hi_boot_file) + ; mb_found <- ioToIOEnv (findHiFile hsc_env mod hi_boot_file) ; case mb_found of { Failed err -> do { traceIf (ptext SLIT("...not found")) ; dflags <- getDOpts - ; returnM (Failed (cantFindError dflags mod_name err)) } ; + ; returnM (Failed (cantFindError dflags (moduleName mod) err)) } ; - Succeeded (file_path, pkg) -> do + Succeeded file_path -> do -- Found file, so read it { traceIf (ptext SLIT("readIFace") <+> text file_path) - ; read_result <- readIface mod_name file_path hi_boot_file + ; read_result <- readIface mod file_path hi_boot_file ; case read_result of Failed err -> returnM (Failed (badIfaceFile file_path err)) Succeeded iface - | mi_module iface /= mod_name -> - return (Failed (wrongIfaceModErr iface mod_name file_path)) + | mi_module iface /= mod -> + return (Failed (wrongIfaceModErr iface mod file_path)) | otherwise -> - returnM (Succeeded (iface{mi_package=pkg}, file_path)) + returnM (Succeeded (iface, file_path)) -- Don't forget to fill in the package name... }}} -findHiFile :: HscEnv -> Bool -> Module -> IsBootInterface - -> IO (MaybeErr FindResult (FilePath, PackageIdH)) -findHiFile hsc_env explicit mod_name hi_boot_file - = do { - -- In interactive or --make mode, we are *not allowed* to demand-load - -- a home package .hi file. So don't even look for them. - -- This helps in the case where you are sitting in eg. ghc/lib/std - -- and start up GHCi - it won't complain that all the modules it tries - -- to load are found in the home location. - let { home_allowed = isOneShot (ghcMode (hsc_dflags hsc_env)) } ; - maybe_found <- if home_allowed - then findModule hsc_env mod_name explicit - else findPackageModule hsc_env mod_name explicit; - - case maybe_found of - Found loc pkg -> return (Succeeded (path, pkg)) - where - path = addBootSuffix_maybe hi_boot_file (ml_hi_file loc) - - err -> return (Failed err) - } +findHiFile :: HscEnv -> Module -> IsBootInterface + -> IO (MaybeErr FindResult FilePath) +findHiFile hsc_env mod hi_boot_file + = do + maybe_found <- findExactModule hsc_env mod + case maybe_found of + Found loc mod -> return (Succeeded path) + where + path = addBootSuffix_maybe hi_boot_file (ml_hi_file loc) + err -> return (Failed err) \end{code} @readIface@ tries just the one file. \begin{code} -readIface :: Module -> String -> IsBootInterface +readIface :: Module -> FilePath -> IsBootInterface -> TcRnIf gbl lcl (MaybeErr Message ModIface) -- Failed err <=> file not found, or unreadable, or illegible -- Succeeded iface <=> successfully found and parsed @@ -493,7 +483,7 @@ readIface wanted_mod file_path is_hi_boot_file initExternalPackageState :: ExternalPackageState initExternalPackageState = EPS { - eps_is_boot = emptyModuleEnv, + eps_is_boot = emptyUFM, eps_PIT = emptyPackageIfaceTable, eps_PTE = emptyTypeEnv, eps_inst_env = emptyInstEnv, @@ -515,7 +505,7 @@ initExternalPackageState \begin{code} ghcPrimIface :: ModIface ghcPrimIface - = (emptyModIface HomePackage gHC_PRIM) { + = (emptyModIface gHC_PRIM) { mi_exports = [(gHC_PRIM, ghcPrimExports)], mi_decls = [], mi_fixities = fixities, @@ -563,7 +553,10 @@ badIfaceFile file err hiModuleNameMismatchWarn :: Module -> Module -> Message hiModuleNameMismatchWarn requested_mod read_mod = - hsep [ ptext SLIT("Something is amiss; requested module name") + withPprStyle defaultUserStyle $ + -- we want the Modules below to be qualified with package names, + -- so reset the PrintUnqualified setting. + hsep [ ptext SLIT("Something is amiss; requested module ") , ppr requested_mod , ptext SLIT("differs from name found in the interface file") , ppr read_mod diff --git a/compiler/iface/MkIface.lhs b/compiler/iface/MkIface.lhs index 3ff30d971a..b86aa92493 100644 --- a/compiler/iface/MkIface.lhs +++ b/compiler/iface/MkIface.lhs @@ -176,7 +176,6 @@ compiled with -O. I think this is the case.] #include "HsVersions.h" import HsSyn -import Packages ( isHomeModule, PackageIdH(..) ) import IfaceSyn ( IfaceDecl(..), IfaceClassOp(..), IfaceConDecl(..), IfaceRule(..), IfaceInst(..), IfaceExtName(..), eqIfDecl, eqIfRule, eqIfInst, IfaceEq(..), (&&&), bool, @@ -199,7 +198,6 @@ import HscTypes ( ModIface(..), ModDetails(..), ) -import Packages ( HomeModules ) import DynFlags ( GhcMode(..), DynFlags(..), DynFlag(..), dopt ) import StaticFlags ( opt_HiVersion ) import Name ( Name, nameModule, nameOccName, nameParent, @@ -213,11 +211,7 @@ import OccName ( OccName, OccEnv, mkOccEnv, lookupOccEnv, emptyOccEnv, extendOccSet, extendOccSetList, isEmptyOccSet, intersectOccSet, intersectsOccSet, occNameFS, isTcOcc ) -import Module ( Module, moduleFS, - ModLocation(..), mkModuleFS, moduleString, - ModuleEnv, emptyModuleEnv, lookupModuleEnv, - extendModuleEnv_C - ) +import Module import Outputable import Util ( createDirectoryHierarchy, directoryOf ) import Util ( sortLe, seqList ) @@ -227,6 +221,8 @@ import Unique ( Unique, Uniquable(..) ) import ErrUtils ( dumpIfSet_dyn, showPass ) import Digraph ( stronglyConnComp, SCC(..) ) import SrcLoc ( SrcSpan ) +import UniqFM +import PackageConfig ( PackageId ) import FiniteMap import FastString @@ -259,7 +255,6 @@ mkIface hsc_env maybe_old_iface mg_boot = is_boot, mg_usages = usages, mg_deps = deps, - mg_home_mods = home_mods, mg_rdr_env = rdr_env, mg_fix_env = fix_env, mg_deprecs = src_deprecs }) @@ -274,7 +269,7 @@ mkIface hsc_env maybe_old_iface -- to expose in the interface = do { eps <- hscEPS hsc_env - ; let { ext_nm_rhs = mkExtNameFn hsc_env home_mods eps this_mod + ; let { ext_nm_rhs = mkExtNameFn hsc_env eps this_mod ; ext_nm_lhs = mkLhsNameFn this_mod ; decls = [ tyThingToIfaceDecl ext_nm_rhs thing @@ -291,7 +286,6 @@ mkIface hsc_env maybe_old_iface ; intermediate_iface = ModIface { mi_module = this_mod, - mi_package = HomePackage, mi_boot = is_boot, mi_deps = deps, mi_usages = usages, @@ -346,8 +340,8 @@ writeIfaceFile location new_iface ----------------------------- -mkExtNameFn :: HscEnv -> HomeModules -> ExternalPackageState -> Module -> Name -> IfaceExtName -mkExtNameFn hsc_env hmods eps this_mod +mkExtNameFn :: HscEnv -> ExternalPackageState -> Module -> Name -> IfaceExtName +mkExtNameFn hsc_env eps this_mod = ext_nm where hpt = hsc_HPT hsc_env @@ -358,10 +352,15 @@ mkExtNameFn hsc_env hmods eps this_mod Nothing -> LocalTop occ Just par -> LocalTopSub occ (nameOccName par) | isWiredInName name = ExtPkg mod occ - | isHomeModule hmods mod = HomePkg mod occ vers + | 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 @@ -374,7 +373,7 @@ mkExtNameFn hsc_env hmods eps this_mod = mi_ver_fn iface occ `orElse` pprPanic "lookupVers1" (ppr mod <+> ppr occ) where - iface = lookupIfaceByModule hpt pit mod `orElse` + iface = lookupIfaceByModule (hsc_dflags hsc_env) hpt pit mod `orElse` pprPanic "lookupVers2" (ppr mod <+> ppr occ) @@ -636,24 +635,24 @@ bump_unless False v = bumpVersion v \begin{code} mkUsageInfo :: HscEnv - -> HomeModules -> ModuleEnv (Module, Bool, SrcSpan) - -> [(Module, IsBootInterface)] + -> [(ModuleName, IsBootInterface)] -> NameSet -> IO [Usage] -mkUsageInfo hsc_env hmods dir_imp_mods dep_mods used_names +mkUsageInfo hsc_env dir_imp_mods dep_mods used_names = do { eps <- hscEPS hsc_env - ; let usages = mk_usage_info (eps_PIT eps) hsc_env hmods + ; let usages = mk_usage_info (eps_PIT eps) hsc_env dir_imp_mods dep_mods used_names ; usages `seqList` return usages } -- seq the list of Usages returned: occasionally these -- 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 hmods dir_imp_mods dep_mods proto_used_names +mk_usage_info pit hsc_env dir_imp_mods dep_mods proto_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 @@ -682,28 +681,28 @@ mk_usage_info pit hsc_env hmods dir_imp_mods dep_mods proto_used_names -- (need to recompile if its export list changes: export_vers) -- c) is a home-package orphan module (need to recompile if its -- instance decls change: rules_vers) - mkUsage :: (Module, Bool) -> Maybe Usage + mkUsage :: (ModuleName, IsBootInterface) -> Maybe Usage mkUsage (mod_name, _) - | isNothing maybe_iface -- We can't depend on it if we didn't - || not (isHomeModule hmods mod) -- even open the interface! - || (null used_occs + | isNothing maybe_iface -- We can't depend on it if we didn't + || (null used_occs -- load its interface. && isNothing export_vers && not orphan_mod) = Nothing -- Record no usage info | otherwise - = Just (Usage { usg_name = mod, + = Just (Usage { usg_name = mod_name, usg_mod = mod_vers, usg_exports = export_vers, usg_entities = ent_vers, usg_rules = rules_vers }) where - maybe_iface = lookupIfaceByModule hpt pit mod_name + maybe_iface = lookupIfaceByModule dflags hpt pit mod -- In one-shot mode, the interfaces for home-package -- modules accumulate in the PIT not HPT. Sigh. + mod = mkModule (thisPackage dflags) mod_name + Just iface = maybe_iface - mod = mi_module iface orphan_mod = mi_orphan iface version_env = mi_ver_fn iface mod_vers = mi_mod_vers iface @@ -723,25 +722,25 @@ mkIfaceExports :: NameSet -> [(Module, [GenAvailInfo OccName])] -- Group by module and sort by occurrence -- This keeps the list in canonical order mkIfaceExports exports - = [ (mkModuleFS fs, eltsFM avails) - | (fs, avails) <- fmToList groupFM + = [ (mod, eltsUFM avails) + | (mod, avails) <- fmToList groupFM ] where - groupFM :: FiniteMap FastString (FiniteMap FastString (GenAvailInfo OccName)) + groupFM :: ModuleEnv (UniqFM (GenAvailInfo OccName)) -- Deliberately use the FastString so we -- get a canonical ordering - groupFM = foldl add emptyFM (nameSetToList exports) + groupFM = foldl add emptyModuleEnv (nameSetToList exports) - add env name = addToFM_C add_avail env mod_fs - (unitFM avail_fs avail) + add env name = extendModuleEnv_C add_avail env mod + (unitUFM avail_fs avail) where occ = nameOccName name - mod_fs = moduleFS (nameModule 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 _ = addToFM_C add_item avail_fm avail_fs 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) @@ -765,13 +764,14 @@ checkOldIface :: HscEnv checkOldIface hsc_env mod_summary source_unchanged maybe_iface = do { showPass (hsc_dflags hsc_env) - ("Checking old interface for " ++ moduleString (ms_mod mod_summary)) ; + ("Checking old interface for " ++ + showSDoc (ppr (ms_mod mod_summary))) ; ; initIfaceCheck hsc_env $ - check_old_iface mod_summary source_unchanged maybe_iface + check_old_iface hsc_env mod_summary source_unchanged maybe_iface } -check_old_iface mod_summary source_unchanged maybe_iface +check_old_iface hsc_env mod_summary source_unchanged maybe_iface = -- CHECK WHETHER THE SOURCE HAS CHANGED ifM (not source_unchanged) (traceHiDiffs (nest 4 (text "Source file changed or recompilation check turned off"))) @@ -786,9 +786,9 @@ check_old_iface mod_summary source_unchanged maybe_iface else case maybe_iface of { - Just old_iface -> -- Use the one we already have - checkVersions source_unchanged old_iface `thenM` \ recomp -> - returnM (recomp, Just old_iface) + Just old_iface -> do -- Use the one we already have + recomp <- checkVersions hsc_env source_unchanged old_iface + return (recomp, Just old_iface) ; Nothing -> @@ -807,7 +807,7 @@ check_old_iface mod_summary source_unchanged maybe_iface ; Succeeded iface -> -- We have got the old iface; check its versions - checkVersions source_unchanged iface `thenM` \ recomp -> + checkVersions hsc_env source_unchanged iface `thenM` \ recomp -> returnM (recomp, Just iface) }} \end{code} @@ -822,10 +822,11 @@ type RecompileRequired = Bool upToDate = False -- Recompile not required outOfDate = True -- Recompile required -checkVersions :: Bool -- True <=> source unchanged +checkVersions :: HscEnv + -> Bool -- True <=> source unchanged -> ModIface -- Old interface -> IfG RecompileRequired -checkVersions source_unchanged iface +checkVersions hsc_env source_unchanged iface | not source_unchanged = returnM outOfDate | otherwise @@ -844,29 +845,33 @@ checkVersions source_unchanged iface -- We do this regardless of compilation mode ; updateEps_ $ \eps -> eps { eps_is_boot = mod_deps } - ; checkList [checkModUsage u | u <- mi_usages iface] + ; let this_pkg = thisPackage (hsc_dflags hsc_env) + ; checkList [checkModUsage this_pkg u | u <- mi_usages iface] } where -- This is a bit of a hack really - mod_deps :: ModuleEnv (Module, IsBootInterface) + mod_deps :: ModuleNameEnv (ModuleName, IsBootInterface) mod_deps = mkModDeps (dep_mods (mi_deps iface)) -checkModUsage :: Usage -> IfG RecompileRequired +checkModUsage :: PackageId ->Usage -> IfG RecompileRequired -- Given the usage information extracted from the old -- M.hi file for the module being compiled, figure out -- whether M needs to be recompiled. -checkModUsage (Usage { usg_name = mod_name, usg_mod = old_mod_vers, - usg_rules = old_rule_vers, - usg_exports = maybe_old_export_vers, - usg_entities = old_decl_vers }) +checkModUsage this_pkg (Usage { usg_name = mod_name, usg_mod = old_mod_vers, + usg_rules = old_rule_vers, + usg_exports = maybe_old_export_vers, + usg_entities = old_decl_vers }) = -- Load the imported interface is possible let doc_str = sep [ptext SLIT("need version info for"), ppr mod_name] in traceHiDiffs (text "Checking usages for module" <+> ppr mod_name) `thenM_` - loadInterface doc_str mod_name ImportBySystem `thenM` \ mb_iface -> + let + mod = mkModule this_pkg mod_name + in + loadInterface doc_str mod ImportBySystem `thenM` \ mb_iface -> -- Load the interface, but don't complain on failure; -- Instead, get an Either back which we can test @@ -977,7 +982,6 @@ pprModIface :: ModIface -> SDoc -- Show a ModIface pprModIface iface = vcat [ ptext SLIT("interface") - <+> ppr_package (mi_package iface) <+> ppr (mi_module iface) <+> pp_boot <+> ppr (mi_mod_vers iface) <+> pp_sub_vers <+> (if mi_orphan iface then ptext SLIT("[orphan module]") else empty) @@ -995,8 +999,6 @@ pprModIface iface where pp_boot | mi_boot iface = ptext SLIT("[boot]") | otherwise = empty - ppr_package HomePackage = empty - ppr_package (ExtPackage id) = doubleQuotes (ppr id) exp_vers = mi_exp_vers iface rule_vers = mi_rule_vers iface diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs index 0b4df3336e..bd31cc04db 100644 --- a/compiler/iface/TcIface.lhs +++ b/compiler/iface/TcIface.lhs @@ -53,7 +53,8 @@ import Name ( Name, nameModule, nameIsLocalOrFrom, isWiredInName, import NameEnv import OccName ( OccName, mkVarOccFS, mkTyVarOcc ) import FastString ( FastString ) -import Module ( Module, lookupModuleEnv ) +import Module ( Module, moduleName ) +import UniqFM ( lookupUFM ) import UniqSupply ( initUs_ ) import Outputable import ErrUtils ( Message ) @@ -246,7 +247,7 @@ tcHiBootIface mod -- And that's fine, because if M's ModInfo is in the HPT, then -- it's been compiled once, and we don't need to check the boot iface then do { hpt <- getHpt - ; case lookupModuleEnv hpt mod of + ; case lookupUFM hpt (moduleName mod) of Just info | mi_boot (hm_iface info) -> return (hm_details info) other -> return emptyModDetails } @@ -257,17 +258,16 @@ tcHiBootIface mod -- so eps_is_boot will record if any of our imports mention us by -- way of hi-boot file { eps <- getEps - ; case lookupModuleEnv (eps_is_boot eps) mod of { + ; case lookupUFM (eps_is_boot eps) (moduleName mod) of { Nothing -> return emptyModDetails ; -- The typical case Just (_, False) -> failWithTc moduleLoop ; -- Someone below us imported us! -- This is a loop with no hi-boot in the way - Just (mod, True) -> -- There's a hi-boot interface below us + Just (_mod, True) -> -- There's a hi-boot interface below us do { read_result <- findAndReadIface - True -- Explicit import? need mod True -- Hi-boot file @@ -843,7 +843,8 @@ tcIfaceGlobal name -- and its RULES are loaded too | otherwise = do { (eps,hpt) <- getEpsAndHpt - ; case lookupType hpt (eps_PTE eps) name of { + ; dflags <- getDOpts + ; case lookupType dflags hpt (eps_PTE eps) name of { Just thing -> return thing ; Nothing -> do |