diff options
author | Edward Z. Yang <ezyang@cs.stanford.edu> | 2016-10-06 00:17:15 -0700 |
---|---|---|
committer | Edward Z. Yang <ezyang@cs.stanford.edu> | 2016-10-08 01:37:33 -0700 |
commit | 4e8a0607140b23561248a41aeaf837224aa6315b (patch) | |
tree | 8e03945afe5c40c13b41667e0175f14db15d0780 /compiler/main | |
parent | 00b530d5402aaa37e4085ecdcae0ae54454736c1 (diff) | |
download | haskell-4e8a0607140b23561248a41aeaf837224aa6315b.tar.gz |
Distinguish between UnitId and InstalledUnitId.
Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
Diffstat (limited to 'compiler/main')
-rw-r--r-- | compiler/main/CodeOutput.hs | 6 | ||||
-rw-r--r-- | compiler/main/DriverPipeline.hs | 24 | ||||
-rw-r--r-- | compiler/main/Finder.hs | 203 | ||||
-rw-r--r-- | compiler/main/GHC.hs | 6 | ||||
-rw-r--r-- | compiler/main/GhcMake.hs | 3 | ||||
-rw-r--r-- | compiler/main/HscMain.hs | 22 | ||||
-rw-r--r-- | compiler/main/HscTypes.hs | 27 | ||||
-rw-r--r-- | compiler/main/PackageConfig.hs | 23 | ||||
-rw-r--r-- | compiler/main/Packages.hs | 186 | ||||
-rw-r--r-- | compiler/main/SysTools.hs | 4 |
10 files changed, 324 insertions, 180 deletions
diff --git a/compiler/main/CodeOutput.hs b/compiler/main/CodeOutput.hs index f172cf1259..f4681dcd27 100644 --- a/compiler/main/CodeOutput.hs +++ b/compiler/main/CodeOutput.hs @@ -50,7 +50,7 @@ codeOutput :: DynFlags -> FilePath -> ModLocation -> ForeignStubs - -> [UnitId] + -> [InstalledUnitId] -> Stream IO RawCmmGroup () -- Compiled C-- -> IO (FilePath, (Bool{-stub_h_exists-}, Maybe FilePath{-stub_c_exists-})) @@ -107,7 +107,7 @@ doOutput filenm io_action = bracket (openFile filenm WriteMode) hClose io_action outputC :: DynFlags -> FilePath -> Stream IO RawCmmGroup () - -> [UnitId] + -> [InstalledUnitId] -> IO () outputC dflags filenm cmm_stream packages @@ -131,7 +131,7 @@ outputC dflags filenm cmm_stream packages '<':_ -> "#include "++h_file _ -> "#include \""++h_file++"\"" - let pkg_names = map unitIdString packages + let pkg_names = map installedUnitIdString packages doOutput filenm $ \ h -> do hPutStr h ("/* GHC_PACKAGES " ++ unwords pkg_names ++ "\n*/\n") diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs index 30493f123e..b1f1f6c2e6 100644 --- a/compiler/main/DriverPipeline.hs +++ b/compiler/main/DriverPipeline.hs @@ -402,7 +402,7 @@ link' dflags batch_attempt_linking hpt return Succeeded -linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [UnitId] -> IO Bool +linkingNeeded :: DynFlags -> Bool -> [Linkable] -> [InstalledUnitId] -> IO Bool linkingNeeded dflags staticLink linkables pkg_deps = do -- if the modification time on the executable is later than the -- modification times on all of the objects and libraries, then omit @@ -424,7 +424,7 @@ linkingNeeded dflags staticLink linkables pkg_deps = do -- next, check libraries. XXX this only checks Haskell libraries, -- not extra_libraries or -l things from the command line. let pkg_hslibs = [ (libraryDirs c, lib) - | Just c <- map (lookupPackage dflags) pkg_deps, + | Just c <- map (lookupInstalledPackage dflags) pkg_deps, lib <- packageHsLibs dflags c ] pkg_libfiles <- mapM (uncurry (findHSLib dflags)) pkg_hslibs @@ -438,7 +438,7 @@ linkingNeeded dflags staticLink linkables pkg_deps = do -- Returns 'False' if it was, and we can avoid linking, because the -- previous binary was linked with "the same options". -checkLinkInfo :: DynFlags -> [UnitId] -> FilePath -> IO Bool +checkLinkInfo :: DynFlags -> [InstalledUnitId] -> FilePath -> IO Bool checkLinkInfo dflags pkg_deps exe_file | not (platformSupportsSavingLinkOpts (platformOS (targetPlatform dflags))) -- ToDo: Windows and OS X do not use the ELF binary format, so @@ -1652,7 +1652,7 @@ mkExtraObjToLinkIntoBinary dflags = do -- this was included as inline assembly in the main.c file but this -- is pretty fragile. gas gets upset trying to calculate relative offsets -- that span the .note section (notably .text) when debug info is present -mkNoteObjsToLinkIntoBinary :: DynFlags -> [UnitId] -> IO [FilePath] +mkNoteObjsToLinkIntoBinary :: DynFlags -> [InstalledUnitId] -> IO [FilePath] mkNoteObjsToLinkIntoBinary dflags dep_packages = do link_info <- getLinkInfo dflags dep_packages @@ -1677,7 +1677,7 @@ mkNoteObjsToLinkIntoBinary dflags dep_packages = do -- | Return the "link info" string -- -- See Note [LinkInfo section] -getLinkInfo :: DynFlags -> [UnitId] -> IO String +getLinkInfo :: DynFlags -> [InstalledUnitId] -> IO String getLinkInfo dflags dep_packages = do package_link_opts <- getPackageLinkOpts dflags dep_packages pkg_frameworks <- if platformUsesFrameworks (targetPlatform dflags) @@ -1714,13 +1714,13 @@ not follow the specified record-based format (see #11022). ----------------------------------------------------------------------------- -- Look for the /* GHC_PACKAGES ... */ comment at the top of a .hc file -getHCFilePackages :: FilePath -> IO [UnitId] +getHCFilePackages :: FilePath -> IO [InstalledUnitId] getHCFilePackages filename = Exception.bracket (openFile filename ReadMode) hClose $ \h -> do l <- hGetLine h case l of '/':'*':' ':'G':'H':'C':'_':'P':'A':'C':'K':'A':'G':'E':'S':rest -> - return (map stringToUnitId (words rest)) + return (map stringToInstalledUnitId (words rest)) _other -> return [] @@ -1737,10 +1737,10 @@ getHCFilePackages filename = -- read any interface files), so the user must explicitly specify all -- the packages. -linkBinary :: DynFlags -> [FilePath] -> [UnitId] -> IO () +linkBinary :: DynFlags -> [FilePath] -> [InstalledUnitId] -> IO () linkBinary = linkBinary' False -linkBinary' :: Bool -> DynFlags -> [FilePath] -> [UnitId] -> IO () +linkBinary' :: Bool -> DynFlags -> [FilePath] -> [InstalledUnitId] -> IO () linkBinary' staticLink dflags o_files dep_packages = do let platform = targetPlatform dflags mySettings = settings dflags @@ -1987,7 +1987,7 @@ maybeCreateManifest dflags exe_filename | otherwise = return [] -linkDynLibCheck :: DynFlags -> [String] -> [UnitId] -> IO () +linkDynLibCheck :: DynFlags -> [String] -> [InstalledUnitId] -> IO () linkDynLibCheck dflags o_files dep_packages = do when (haveRtsOptsFlags dflags) $ do @@ -1997,7 +1997,7 @@ linkDynLibCheck dflags o_files dep_packages linkDynLib dflags o_files dep_packages -linkStaticLibCheck :: DynFlags -> [String] -> [UnitId] -> IO () +linkStaticLibCheck :: DynFlags -> [String] -> [InstalledUnitId] -> IO () linkStaticLibCheck dflags o_files dep_packages = do when (platformOS (targetPlatform dflags) `notElem` [OSiOS, OSDarwin]) $ @@ -2229,7 +2229,7 @@ haveRtsOptsFlags dflags = -- | Find out path to @ghcversion.h@ file getGhcVersionPathName :: DynFlags -> IO FilePath getGhcVersionPathName dflags = do - dirs <- getPackageIncludePath dflags [rtsUnitId] + dirs <- getPackageIncludePath dflags [toInstalledUnitId rtsUnitId] found <- filterM doesFileExist (map (</> "ghcversion.h") dirs) case found of diff --git a/compiler/main/Finder.hs b/compiler/main/Finder.hs index e813e9e52c..2bcdd3360c 100644 --- a/compiler/main/Finder.hs +++ b/compiler/main/Finder.hs @@ -71,25 +71,25 @@ type BaseName = String -- Basename of file -- assumed to not move around during a session. flushFinderCaches :: HscEnv -> IO () flushFinderCaches hsc_env = - atomicModifyIORef' fc_ref $ \fm -> (filterModuleEnv is_ext fm, ()) + atomicModifyIORef' fc_ref $ \fm -> (filterInstalledModuleEnv is_ext fm, ()) where this_pkg = thisPackage (hsc_dflags hsc_env) fc_ref = hsc_FC hsc_env - is_ext mod _ | moduleUnitId mod /= this_pkg = True + is_ext mod _ | not (installedModuleUnitId mod `installedUnitIdEq` this_pkg) = True | otherwise = False -addToFinderCache :: IORef FinderCache -> Module -> FindResult -> IO () +addToFinderCache :: IORef FinderCache -> InstalledModule -> InstalledFindResult -> IO () addToFinderCache ref key val = - atomicModifyIORef' ref $ \c -> (extendModuleEnv c key val, ()) + atomicModifyIORef' ref $ \c -> (extendInstalledModuleEnv c key val, ()) -removeFromFinderCache :: IORef FinderCache -> Module -> IO () +removeFromFinderCache :: IORef FinderCache -> InstalledModule -> IO () removeFromFinderCache ref key = - atomicModifyIORef' ref $ \c -> (delModuleEnv c key, ()) + atomicModifyIORef' ref $ \c -> (delInstalledModuleEnv c key, ()) -lookupFinderCache :: IORef FinderCache -> VirginModule -> IO (Maybe FindResult) +lookupFinderCache :: IORef FinderCache -> InstalledModule -> IO (Maybe InstalledFindResult) lookupFinderCache ref key = do c <- readIORef ref - return $! lookupModuleEnv c key + return $! lookupInstalledModuleEnv c key -- ----------------------------------------------------------------------------- -- The three external entry points @@ -131,11 +131,11 @@ findPluginModule hsc_env mod_name = -- reading the interface for a module mentioned by another interface, -- for example (a "system import"). -findExactModule :: HscEnv -> VirginModule -> IO FindResult +findExactModule :: HscEnv -> InstalledModule -> IO InstalledFindResult findExactModule hsc_env mod = let dflags = hsc_dflags hsc_env - in if moduleUnitId mod == thisPackage dflags - then findHomeModule hsc_env (moduleName mod) + in if installedModuleUnitId mod `installedUnitIdEq` thisPackage dflags + then findInstalledHomeModule hsc_env (installedModuleName mod) else findPackageModule hsc_env mod -- ----------------------------------------------------------------------------- @@ -169,9 +169,9 @@ orIfNotFound this or_this = do -- been done. Otherwise, do the lookup (with the IO action) and save -- the result in the finder cache and the module location cache (if it -- was successful.) -homeSearchCache :: HscEnv -> ModuleName -> IO FindResult -> IO FindResult +homeSearchCache :: HscEnv -> ModuleName -> IO InstalledFindResult -> IO InstalledFindResult homeSearchCache hsc_env mod_name do_this = do - let mod = mkModule (thisPackage (hsc_dflags hsc_env)) mod_name + let mod = mkHomeInstalledModule (hsc_dflags hsc_env) mod_name modLocationCache hsc_env mod do_this findExposedPackageModule :: HscEnv -> ModuleName -> Maybe FastString @@ -190,8 +190,20 @@ findExposedPluginPackageModule hsc_env mod_name findLookupResult :: HscEnv -> LookupResult -> IO FindResult findLookupResult hsc_env r = case r of - LookupFound m pkg_conf -> - findPackageModule_ hsc_env m pkg_conf + LookupFound m pkg_conf -> do + let im = fst (splitModuleInsts m) + r' <- findPackageModule_ hsc_env im pkg_conf + case r' of + -- TODO: ghc -M is unlikely to do the right thing + -- with just the location of the thing that was + -- instantiated; you probably also need all of the + -- implicit locations from the instances + InstalledFound loc _ -> return (Found loc m) + InstalledNoPackage _ -> return (NoPackage (moduleUnitId m)) + InstalledNotFound fp _ -> return (NotFound{ fr_paths = fp, fr_pkg = Just (moduleUnitId m) + , fr_pkgs_hidden = [] + , fr_mods_hidden = [] + , fr_suggestions = []}) LookupMultiple rs -> return (FoundMultiple rs) LookupHidden pkg_hiddens mod_hiddens -> @@ -205,7 +217,7 @@ findLookupResult hsc_env r = case r of , fr_mods_hidden = [] , fr_suggestions = suggest }) -modLocationCache :: HscEnv -> VirginModule -> IO FindResult -> IO FindResult +modLocationCache :: HscEnv -> InstalledModule -> IO InstalledFindResult -> IO InstalledFindResult modLocationCache hsc_env mod do_this = do m <- lookupFinderCache (hsc_FC hsc_env) mod case m of @@ -215,20 +227,43 @@ modLocationCache hsc_env mod do_this = do addToFinderCache (hsc_FC hsc_env) mod result return result +mkHomeInstalledModule :: DynFlags -> ModuleName -> InstalledModule +mkHomeInstalledModule dflags mod_name = + let iuid = fst (splitUnitIdInsts (thisPackage dflags)) + in InstalledModule iuid mod_name + +-- This returns a module because it's more convenient for users addHomeModuleToFinder :: HscEnv -> ModuleName -> ModLocation -> IO Module addHomeModuleToFinder hsc_env mod_name loc = do - let mod = mkModule (thisPackage (hsc_dflags hsc_env)) mod_name - addToFinderCache (hsc_FC hsc_env) mod (Found loc mod) - return mod + let mod = mkHomeInstalledModule (hsc_dflags hsc_env) mod_name + addToFinderCache (hsc_FC hsc_env) mod (InstalledFound loc mod) + return (mkModule (thisPackage (hsc_dflags hsc_env)) mod_name) uncacheModule :: HscEnv -> ModuleName -> IO () -uncacheModule hsc_env mod = do - let this_pkg = thisPackage (hsc_dflags hsc_env) - removeFromFinderCache (hsc_FC hsc_env) (mkModule this_pkg mod) +uncacheModule hsc_env mod_name = do + let mod = mkHomeInstalledModule (hsc_dflags hsc_env) mod_name + removeFromFinderCache (hsc_FC hsc_env) mod -- ----------------------------------------------------------------------------- -- The internal workers +findHomeModule :: HscEnv -> ModuleName -> IO FindResult +findHomeModule hsc_env mod_name = do + r <- findInstalledHomeModule hsc_env mod_name + return $ case r of + InstalledFound loc _ -> Found loc (mkModule uid mod_name) + InstalledNoPackage _ -> NoPackage uid -- impossible + InstalledNotFound fps _ -> NotFound { + fr_paths = fps, + fr_pkg = Just uid, + fr_mods_hidden = [], + fr_pkgs_hidden = [], + fr_suggestions = [] + } + where + dflags = hsc_dflags hsc_env + uid = thisPackage dflags + -- | Implements the search for a module name in the home package only. Calling -- this function directly is usually *not* what you want; currently, it's used -- as a building block for the following operations: @@ -245,14 +280,14 @@ uncacheModule hsc_env mod = do -- -- 4. Some special-case code in GHCi (ToDo: Figure out why that needs to -- call this.) -findHomeModule :: HscEnv -> ModuleName -> IO FindResult -findHomeModule hsc_env mod_name = +findInstalledHomeModule :: HscEnv -> ModuleName -> IO InstalledFindResult +findInstalledHomeModule hsc_env mod_name = homeSearchCache hsc_env mod_name $ let dflags = hsc_dflags hsc_env home_path = importPaths dflags hisuf = hiSuf dflags - mod = mkModule (thisPackage dflags) mod_name + mod = mkHomeInstalledModule dflags mod_name source_exts = [ ("hs", mkHomeModLocationSearched dflags mod_name "hs") @@ -275,20 +310,20 @@ findHomeModule hsc_env mod_name = -- special case for GHC.Prim; we won't find it in the filesystem. -- This is important only when compiling the base package (where GHC.Prim -- is a home module). - if mod == gHC_PRIM - then return (Found (error "GHC.Prim ModLocation") mod) + if mod `installedModuleEq` gHC_PRIM + then return (InstalledFound (error "GHC.Prim ModLocation") mod) else searchPathExts home_path mod exts -- | Search for a module in external packages only. -findPackageModule :: HscEnv -> VirginModule -> IO FindResult +findPackageModule :: HscEnv -> InstalledModule -> IO InstalledFindResult findPackageModule hsc_env mod = do let dflags = hsc_dflags hsc_env - pkg_id = moduleUnitId mod + pkg_id = installedModuleUnitId mod -- - case lookupPackage dflags pkg_id of - Nothing -> return (NoPackage pkg_id) + case lookupInstalledPackage dflags pkg_id of + Nothing -> return (InstalledNoPackage pkg_id) Just pkg_conf -> findPackageModule_ hsc_env mod pkg_conf -- | Look up the interface file associated with module @mod@. This function @@ -298,14 +333,14 @@ findPackageModule hsc_env mod = do -- the 'PackageConfig' must be consistent with the unit id in the 'Module'. -- The redundancy is to avoid an extra lookup in the package state -- for the appropriate config. -findPackageModule_ :: HscEnv -> VirginModule -> PackageConfig -> IO FindResult +findPackageModule_ :: HscEnv -> InstalledModule -> PackageConfig -> IO InstalledFindResult findPackageModule_ hsc_env mod pkg_conf = - ASSERT( moduleUnitId mod == packageConfigId pkg_conf ) + ASSERT( installedModuleUnitId mod == installedPackageConfigId pkg_conf ) modLocationCache hsc_env mod $ -- special case for GHC.Prim; we won't find it in the filesystem. - if mod == gHC_PRIM - then return (Found (error "GHC.Prim ModLocation") mod) + if mod `installedModuleEq` gHC_PRIM + then return (InstalledFound (error "GHC.Prim ModLocation") mod) else let @@ -326,9 +361,9 @@ findPackageModule_ hsc_env mod pkg_conf = [one] | MkDepend <- ghcMode dflags -> do -- there's only one place that this .hi file can be, so -- don't bother looking for it. - let basename = moduleNameSlashes (moduleName mod) + let basename = moduleNameSlashes (installedModuleName mod) loc <- mk_hi_loc one basename - return (Found loc mod) + return (InstalledFound loc mod) _otherwise -> searchPathExts import_dirs mod [(package_hisuf, mk_hi_loc)] @@ -337,13 +372,13 @@ findPackageModule_ hsc_env mod pkg_conf = searchPathExts :: [FilePath] -- paths to search - -> Module -- module name + -> InstalledModule -- module name -> [ ( FileExt, -- suffix FilePath -> BaseName -> IO ModLocation -- action ) ] - -> IO FindResult + -> IO InstalledFindResult searchPathExts paths mod exts = do result <- search to_search @@ -358,7 +393,7 @@ searchPathExts paths mod exts return result where - basename = moduleNameSlashes (moduleName mod) + basename = moduleNameSlashes (installedModuleName mod) to_search :: [(FilePath, IO ModLocation)] to_search = [ (file, fn path basename) @@ -369,15 +404,12 @@ searchPathExts paths mod exts file = base <.> ext ] - search [] = return (NotFound { fr_paths = map fst to_search - , fr_pkg = Just (moduleUnitId mod) - , fr_mods_hidden = [], fr_pkgs_hidden = [] - , fr_suggestions = [] }) + search [] = return (InstalledNotFound (map fst to_search) (Just (installedModuleUnitId mod))) search ((file, mk_result) : rest) = do b <- doesFileExist file if b - then do { loc <- mk_result; return (Found loc mod) } + then do { loc <- mk_result; return (InstalledFound loc mod) } else search rest mkHomeModLocationSearched :: DynFlags -> ModuleName -> FileExt @@ -539,9 +571,9 @@ cannotFindModule :: DynFlags -> ModuleName -> FindResult -> SDoc cannotFindModule = cantFindErr (sLit "Could not find module") (sLit "Ambiguous module name") -cannotFindInterface :: DynFlags -> ModuleName -> FindResult -> SDoc -cannotFindInterface = cantFindErr (sLit "Failed to load interface for") - (sLit "Ambiguous interface for") +cannotFindInterface :: DynFlags -> ModuleName -> InstalledFindResult -> SDoc +cannotFindInterface = cantFindInstalledErr (sLit "Failed to load interface for") + (sLit "Ambiguous interface for") cantFindErr :: LitString -> LitString -> DynFlags -> ModuleName -> FindResult -> SDoc @@ -581,7 +613,7 @@ cantFindErr cannot_find _ dflags mod_name find_result = case find_result of NoPackage pkg -> text "no unit id matching" <+> quotes (ppr pkg) <+> - text "was found" $$ looks_like_srcpkgid pkg + text "was found" NotFound { fr_paths = files, fr_pkg = mb_pkg , fr_mods_hidden = mod_hiddens, fr_pkgs_hidden = pkg_hiddens @@ -642,18 +674,6 @@ cantFindErr cannot_find _ dflags mod_name find_result text "to the build-depends in your .cabal file." | otherwise = Outputable.empty - looks_like_srcpkgid :: UnitId -> SDoc - looks_like_srcpkgid pk - -- Unsafely coerce a unit id FastString into a source package ID - -- FastString and see if it means anything. - | (pkg:pkgs) <- searchPackageId dflags (SourcePackageId (unitIdFS pk)) - = parens (text "This unit ID looks like the source package ID;" $$ - text "the real unit ID is" <+> quotes (ftext (unitIdFS (unitId pkg))) $$ - (if null pkgs then Outputable.empty - else text "and" <+> int (length pkgs) <+> text "other candidates")) - -- Todo: also check if it looks like a package name! - | otherwise = Outputable.empty - mod_hidden pkg = text "it is a hidden module in the package" <+> quotes (ppr pkg) @@ -693,3 +713,64 @@ cantFindErr cannot_find _ dflags mod_name find_result = parens (text "needs flag -package-id" <+> ppr (packageConfigId pkg)) | otherwise = Outputable.empty + +cantFindInstalledErr :: LitString -> LitString -> DynFlags -> ModuleName -> InstalledFindResult + -> SDoc +cantFindInstalledErr cannot_find _ dflags mod_name find_result + = ptext cannot_find <+> quotes (ppr mod_name) + $$ more_info + where + more_info + = case find_result of + InstalledNoPackage pkg + -> text "no unit id matching" <+> quotes (ppr pkg) <+> + text "was found" $$ looks_like_srcpkgid pkg + + InstalledNotFound files mb_pkg + | Just pkg <- mb_pkg, not (pkg `installedUnitIdEq` thisPackage dflags) + -> not_found_in_package pkg files + + | null files + -> text "It is not a module in the current program, or in any known package." + + | otherwise + -> tried_these files + + _ -> panic "cantFindInstalledErr" + + build_tag = buildTag dflags + + looks_like_srcpkgid :: InstalledUnitId -> SDoc + looks_like_srcpkgid pk + -- Unsafely coerce a unit id FastString into a source package ID + -- FastString and see if it means anything. + | (pkg:pkgs) <- searchPackageId dflags (SourcePackageId (installedUnitIdFS pk)) + = parens (text "This unit ID looks like the source package ID;" $$ + text "the real unit ID is" <+> quotes (ftext (installedUnitIdFS (unitId pkg))) $$ + (if null pkgs then Outputable.empty + else text "and" <+> int (length pkgs) <+> text "other candidates")) + -- Todo: also check if it looks like a package name! + | otherwise = Outputable.empty + + not_found_in_package pkg files + | build_tag /= "" + = let + build = if build_tag == "p" then "profiling" + else "\"" ++ build_tag ++ "\"" + in + text "Perhaps you haven't installed the " <> text build <> + text " libraries for package " <> quotes (ppr pkg) <> char '?' $$ + tried_these files + + | otherwise + = text "There are files missing in the " <> quotes (ppr pkg) <> + text " package," $$ + text "try running 'ghc-pkg check'." $$ + tried_these files + + tried_these files + | null files = Outputable.empty + | verbosity dflags < 3 = + text "Use -v to see a list of the files searched for." + | otherwise = + hang (text "Locations searched:") 2 $ vcat (map text files) diff --git a/compiler/main/GHC.hs b/compiler/main/GHC.hs index 6a3887a0e9..5122329acf 100644 --- a/compiler/main/GHC.hs +++ b/compiler/main/GHC.hs @@ -576,7 +576,7 @@ checkBrokenTablesNextToCode' dflags -- flags. If you are not doing linking or doing static linking, you -- can ignore the list of packages returned. -- -setSessionDynFlags :: GhcMonad m => DynFlags -> m [UnitId] +setSessionDynFlags :: GhcMonad m => DynFlags -> m [InstalledUnitId] setSessionDynFlags dflags = do dflags' <- checkNewDynFlags dflags (dflags'', preload) <- liftIO $ initPackages dflags' @@ -586,7 +586,7 @@ setSessionDynFlags dflags = do return preload -- | Sets the program 'DynFlags'. -setProgramDynFlags :: GhcMonad m => DynFlags -> m [UnitId] +setProgramDynFlags :: GhcMonad m => DynFlags -> m [InstalledUnitId] setProgramDynFlags dflags = do dflags' <- checkNewDynFlags dflags (dflags'', preload) <- liftIO $ initPackages dflags' @@ -1435,7 +1435,7 @@ isModuleTrusted m = withSession $ \hsc_env -> liftIO $ hscCheckSafe hsc_env m noSrcSpan -- | Return if a module is trusted and the pkgs it depends on to be trusted. -moduleTrustReqs :: GhcMonad m => Module -> m (Bool, [UnitId]) +moduleTrustReqs :: GhcMonad m => Module -> m (Bool, [InstalledUnitId]) moduleTrustReqs m = withSession $ \hsc_env -> liftIO $ hscGetSafe hsc_env m noSrcSpan diff --git a/compiler/main/GhcMake.hs b/compiler/main/GhcMake.hs index 998d68c11a..0921a58531 100644 --- a/compiler/main/GhcMake.hs +++ b/compiler/main/GhcMake.hs @@ -1916,7 +1916,8 @@ summariseFile hsc_env old_summaries file mb_phase obj_allowed maybe_buf extra_sig_imports <- findExtraSigImports hsc_env hsc_src mod_name required_by_imports <- implicitRequirements hsc_env the_imps - return (ModSummary { ms_mod = mod, ms_hsc_src = hsc_src, + return (ModSummary { ms_mod = mod, + ms_hsc_src = hsc_src, ms_location = location, ms_hspp_file = hspp_fn, ms_hspp_opts = dflags', diff --git a/compiler/main/HscMain.hs b/compiler/main/HscMain.hs index cd8b56843f..ae6ad7d068 100644 --- a/compiler/main/HscMain.hs +++ b/compiler/main/HscMain.hs @@ -179,7 +179,7 @@ newHscEnv dflags = do eps_var <- newIORef initExternalPackageState us <- mkSplitUniqSupply 'r' nc_var <- newIORef (initNameCache us allKnownKeyNames) - fc_var <- newIORef emptyModuleEnv + fc_var <- newIORef emptyInstalledModuleEnv #ifdef GHCI iserv_mvar <- newMVar Nothing #endif @@ -444,12 +444,14 @@ hscTypecheck keep_rn mod_summary mb_rdr_module = do let hsc_src = ms_hsc_src mod_summary dflags = hsc_dflags hsc_env outer_mod = ms_mod mod_summary - inner_mod = canonicalizeHomeModule dflags (moduleName outer_mod) + mod_name = moduleName outer_mod + outer_mod' = mkModule (thisPackage dflags) mod_name + inner_mod = canonicalizeHomeModule dflags mod_name src_filename = ms_hspp_file mod_summary real_loc = realSrcLocSpan $ mkRealSrcLoc (mkFastString src_filename) 1 1 MASSERT( moduleUnitId outer_mod == thisPackage dflags ) if hsc_src == HsigFile && not (isHoleModule inner_mod) - then ioMsgMaybe $ tcRnInstantiateSignature hsc_env outer_mod real_loc + then ioMsgMaybe $ tcRnInstantiateSignature hsc_env outer_mod' real_loc else do hpm <- case mb_rdr_module of Just hpm -> return hpm @@ -1021,7 +1023,7 @@ hscCheckSafe hsc_env m l = runHsc hsc_env $ do return $ isEmptyBag errs -- | Return if a module is trusted and the pkgs it depends on to be trusted. -hscGetSafe :: HscEnv -> Module -> SrcSpan -> IO (Bool, [UnitId]) +hscGetSafe :: HscEnv -> Module -> SrcSpan -> IO (Bool, [InstalledUnitId]) hscGetSafe hsc_env m l = runHsc hsc_env $ do dflags <- getDynFlags (self, pkgs) <- hscCheckSafe' dflags m l @@ -1035,15 +1037,17 @@ hscGetSafe hsc_env m l = runHsc hsc_env $ do -- Return (regardless of trusted or not) if the trust type requires the modules -- own package be trusted and a list of other packages required to be trusted -- (these later ones haven't been checked) but the own package trust has been. -hscCheckSafe' :: DynFlags -> Module -> SrcSpan -> Hsc (Maybe UnitId, [UnitId]) +hscCheckSafe' :: DynFlags -> Module -> SrcSpan -> Hsc (Maybe InstalledUnitId, [InstalledUnitId]) hscCheckSafe' dflags m l = do (tw, pkgs) <- isModSafe m l case tw of False -> return (Nothing, pkgs) True | isHomePkg m -> return (Nothing, pkgs) - | otherwise -> return (Just $ moduleUnitId m, pkgs) + -- TODO: do we also have to check the trust of the instantiation? + -- Not necessary if that is reflected in dependencies + | otherwise -> return (Just $ toInstalledUnitId (moduleUnitId m), pkgs) where - isModSafe :: Module -> SrcSpan -> Hsc (Bool, [UnitId]) + isModSafe :: Module -> SrcSpan -> Hsc (Bool, [InstalledUnitId]) isModSafe m l = do iface <- lookup' m case iface of @@ -1123,7 +1127,7 @@ hscCheckSafe' dflags m l = do | otherwise = False -- | Check the list of packages are trusted. -checkPkgTrust :: DynFlags -> [UnitId] -> Hsc () +checkPkgTrust :: DynFlags -> [InstalledUnitId] -> Hsc () checkPkgTrust dflags pkgs = case errors of [] -> return () @@ -1131,7 +1135,7 @@ checkPkgTrust dflags pkgs = where errors = catMaybes $ map go pkgs go pkg - | trusted $ getPackageDetails dflags pkg + | trusted $ getInstalledPackageDetails dflags pkg = Nothing | otherwise = Just $ mkErrMsg dflags noSrcSpan (pkgQual dflags) diff --git a/compiler/main/HscTypes.hs b/compiler/main/HscTypes.hs index c2d2938b45..1320a57e9a 100644 --- a/compiler/main/HscTypes.hs +++ b/compiler/main/HscTypes.hs @@ -10,7 +10,7 @@ module HscTypes ( -- * compilation state HscEnv(..), hscEPS, - FinderCache, FindResult(..), + FinderCache, FindResult(..), InstalledFindResult(..), Target(..), TargetId(..), pprTarget, pprTargetId, ModuleGraph, emptyMG, HscStatus(..), @@ -26,7 +26,7 @@ module HscTypes ( ModGuts(..), CgGuts(..), ForeignStubs(..), appendStubC, ImportedMods, ImportedModsVal(..), - ModSummary(..), ms_imps, ms_mod_name, showModMsg, isBootSummary, + ModSummary(..), ms_imps, ms_installed_mod, ms_mod_name, showModMsg, isBootSummary, msHsFilePath, msHiFilePath, msObjFilePath, SourceModified(..), @@ -771,16 +771,18 @@ prepareAnnotations hsc_env mb_guts = do -- modules along the search path. On @:load@, we flush the entire -- contents of this cache. -- --- Although the @FinderCache@ range is 'FindResult' for convenience, --- in fact it will only ever contain 'Found' or 'NotFound' entries. --- -type FinderCache = VirginModuleEnv FindResult +type FinderCache = InstalledModuleEnv InstalledFindResult + +data InstalledFindResult + = InstalledFound ModLocation InstalledModule + | InstalledNoPackage InstalledUnitId + | InstalledNotFound [FilePath] (Maybe InstalledUnitId) -- | The result of searching for an imported module. -- -- NB: FindResult manages both user source-import lookups -- (which can result in 'Module') as well as direct imports --- for interfaces (which always result in 'VirginModule'). +-- for interfaces (which always result in 'InstalledModule'). data FindResult = Found ModLocation Module -- ^ The module was found @@ -1272,8 +1274,8 @@ data CgGuts -- as part of the code-gen of tycons cg_foreign :: !ForeignStubs, -- ^ Foreign export stubs - cg_dep_pkgs :: ![UnitId], -- ^ Dependent packages, used to - -- generate #includes for C code gen + cg_dep_pkgs :: ![InstalledUnitId], -- ^ Dependent packages, used to + -- generate #includes for C code gen cg_hpc_info :: !HpcInfo, -- ^ Program coverage tick box information cg_modBreaks :: !(Maybe ModBreaks) -- ^ Module breakpoints } @@ -2240,7 +2242,7 @@ data Dependencies -- I.e. modules that this one imports, or that are in the -- dep_mods of those directly-imported modules - , dep_pkgs :: [(UnitId, Bool)] + , dep_pkgs :: [(InstalledUnitId, Bool)] -- ^ All packages transitively below this module -- I.e. packages to which this module's direct imports belong, -- or that are in the dep_pkgs of those modules @@ -2449,7 +2451,7 @@ data ExternalPackageState -- -- * Deprecations and warnings - eps_free_holes :: ModuleEnv (UniqDSet ModuleName), + eps_free_holes :: InstalledModuleEnv (UniqDSet ModuleName), -- ^ Cache for 'mi_free_holes'. Ordinarily, we can rely on -- the 'eps_PIT' for this information, EXCEPT that when -- we do dependency analysis, we need to look at the @@ -2602,6 +2604,9 @@ data ModSummary -- ^ The actual preprocessed source, if we have it } +ms_installed_mod :: ModSummary -> InstalledModule +ms_installed_mod = fst . splitModuleInsts . ms_mod + ms_mod_name :: ModSummary -> ModuleName ms_mod_name = moduleName . ms_mod diff --git a/compiler/main/PackageConfig.hs b/compiler/main/PackageConfig.hs index f16c902a7e..6e3e2f1c9b 100644 --- a/compiler/main/PackageConfig.hs +++ b/compiler/main/PackageConfig.hs @@ -12,6 +12,8 @@ module PackageConfig ( -- * UnitId packageConfigId, expandedPackageConfigId, + definitePackageConfigId, + installedPackageConfigId, -- * The PackageConfig type: information about a package PackageConfig, @@ -35,6 +37,7 @@ import FastString import Outputable import Module import Unique +import UniqDSet -- ----------------------------------------------------------------------------- -- Our PackageConfig type is the InstalledPackageInfo from ghc-boot, @@ -44,7 +47,7 @@ type PackageConfig = InstalledPackageInfo ComponentId SourcePackageId PackageName - Module.UnitId + Module.InstalledUnitId Module.UnitId Module.ModuleName Module.Module @@ -129,11 +132,21 @@ pprPackageConfig InstalledPackageInfo {..} = -- version is, so these are handled specially; see #wired_in_packages#. -- | Get the GHC 'UnitId' right out of a Cabalish 'PackageConfig' +installedPackageConfigId :: PackageConfig -> InstalledUnitId +installedPackageConfigId = unitId + packageConfigId :: PackageConfig -> UnitId -packageConfigId = unitId +packageConfigId p = + if indefinite p + then newUnitId (installedUnitIdComponentId (unitId p)) (instantiatedWith p) + else DefiniteUnitId (DefUnitId (unitId p)) expandedPackageConfigId :: PackageConfig -> UnitId expandedPackageConfigId p = - case instantiatedWith p of - [] -> packageConfigId p - _ -> newUnitId (unitIdComponentId (packageConfigId p)) (instantiatedWith p) + newUnitId (installedUnitIdComponentId (unitId p)) (instantiatedWith p) + +definitePackageConfigId :: PackageConfig -> Maybe DefUnitId +definitePackageConfigId p = + case packageConfigId p of + DefiniteUnitId def_uid -> Just def_uid + _ -> Nothing diff --git a/compiler/main/Packages.hs b/compiler/main/Packages.hs index 3003e015b6..566d998899 100644 --- a/compiler/main/Packages.hs +++ b/compiler/main/Packages.hs @@ -20,11 +20,12 @@ module Packages ( -- * Querying the package config lookupPackage, lookupPackage', + lookupInstalledPackage, lookupPackageName, - lookupComponentId, improveUnitId, searchPackageId, getPackageDetails, + getInstalledPackageDetails, componentIdString, listVisibleModuleNames, lookupModuleInAllPackages, @@ -65,6 +66,7 @@ import DynFlags import Name ( Name, nameModule_maybe ) import UniqFM import UniqDFM +import UniqSet import Module import Util import Panic @@ -238,12 +240,18 @@ originEmpty :: ModuleOrigin -> Bool originEmpty (ModOrigin Nothing [] [] False) = True originEmpty _ = False --- | 'UniqFM' map from 'UnitId' -type UnitIdMap = UniqDFM - --- | 'UniqFM' map from 'UnitId' to 'PackageConfig' --- (newtyped so we can put it in boot.) -newtype PackageConfigMap = PackageConfigMap { unPackageConfigMap :: UnitIdMap PackageConfig } +-- | 'UniqFM' map from 'InstalledUnitId' +type InstalledUnitIdMap = UniqDFM + +-- | 'UniqFM' map from 'UnitId' to 'PackageConfig', plus +-- the transitive closure of preload packages. +data PackageConfigMap = PackageConfigMap { + unPackageConfigMap :: InstalledUnitIdMap PackageConfig, + -- | The set of transitively reachable packages according + -- to the explicitly provided command line arguments. + -- See Note [UnitId to InstalledUnitId improvement] + preloadClosure :: UniqSet InstalledUnitId + } -- | 'UniqFM' map from 'UnitId' to a 'UnitVisibility'. type VisibilityMap = Map UnitId UnitVisibility @@ -294,6 +302,9 @@ instance Monoid UnitVisibility where , uv_explicit = uv_explicit uv1 || uv_explicit uv2 } +type WiredUnitId = DefUnitId +type PreloadUnitId = InstalledUnitId + -- | Map from 'ModuleName' to 'Module' to all the origins of the bindings -- in scope. The 'PackageConf' is not cached, mostly for convenience reasons -- (since this is the slow path, we'll just look it up again). @@ -314,12 +325,12 @@ data PackageState = PackageState { -- | A mapping from wired in names to the original names from the -- package database. - unwireMap :: Map UnitId UnitId, + unwireMap :: Map WiredUnitId WiredUnitId, -- | The packages we're going to link in eagerly. This list -- should be in reverse dependency order; that is, a package -- is always mentioned before the packages it depends on. - preloadPackages :: [UnitId], + preloadPackages :: [PreloadUnitId], -- | Packages which we explicitly depend on (from a command line flag). -- We'll use this to generate version macros. @@ -355,11 +366,11 @@ emptyPackageState = PackageState { requirementContext = Map.empty } -type InstalledPackageIndex = Map UnitId PackageConfig +type InstalledPackageIndex = Map InstalledUnitId PackageConfig -- | Empty package configuration map emptyPackageConfigMap :: PackageConfigMap -emptyPackageConfigMap = PackageConfigMap emptyUDFM +emptyPackageConfigMap = PackageConfigMap emptyUDFM emptyUniqSet -- | Find the package we know about with the given unit id, if any lookupPackage :: DynFlags -> UnitId -> Maybe PackageConfig @@ -370,14 +381,15 @@ lookupPackage dflags = lookupPackage' (isIndefinite dflags) (pkgIdMap (pkgState -- just a 'PackageConfigMap' rather than a 'DynFlags' (so it can -- be used while we're initializing 'DynFlags' lookupPackage' :: Bool -> PackageConfigMap -> UnitId -> Maybe PackageConfig -lookupPackage' False (PackageConfigMap pkg_map) uid = lookupUDFM pkg_map uid -lookupPackage' True (PackageConfigMap pkg_map) uid = +lookupPackage' False (PackageConfigMap pkg_map _) uid = lookupUDFM pkg_map uid +lookupPackage' True m@(PackageConfigMap pkg_map _) uid = case splitUnitIdInsts uid of (iuid, Just insts) -> - fmap (renamePackage (PackageConfigMap pkg_map) insts) + fmap (renamePackage m insts) (lookupUDFM pkg_map iuid) (_, Nothing) -> lookupUDFM pkg_map uid +{- -- | Find the indefinite package for a given 'ComponentId'. -- The way this works is just by fiat'ing that every indefinite package's -- unit key is precisely its component ID; and that they share uniques. @@ -385,6 +397,7 @@ lookupComponentId :: DynFlags -> ComponentId -> Maybe PackageConfig lookupComponentId dflags (ComponentId cid_fs) = lookupUDFM pkg_map cid_fs where PackageConfigMap pkg_map = pkgIdMap (pkgState dflags) +-} -- | Find the package we know about with the given package name (e.g. @foo@), if any -- (NB: there might be a locally defined unit name which overrides this) @@ -399,12 +412,12 @@ searchPackageId dflags pid = filter ((pid ==) . sourcePackageId) -- | Extends the package configuration map with a list of package configs. extendPackageConfigMap :: PackageConfigMap -> [PackageConfig] -> PackageConfigMap -extendPackageConfigMap (PackageConfigMap pkg_map) new_pkgs - = PackageConfigMap (foldl add pkg_map new_pkgs) +extendPackageConfigMap (PackageConfigMap pkg_map closure) new_pkgs + = PackageConfigMap (foldl add pkg_map new_pkgs) closure -- We also add the expanded version of the packageConfigId, so that -- 'improveUnitId' can find it. where add pkg_map p = addToUDFM (addToUDFM pkg_map (expandedPackageConfigId p) p) - (packageConfigId p) p + (installedPackageConfigId p) p -- | Looks up the package with the given id in the package state, panicing if it is -- not found @@ -412,6 +425,17 @@ getPackageDetails :: DynFlags -> UnitId -> PackageConfig getPackageDetails dflags pid = expectJust "getPackageDetails" (lookupPackage dflags pid) +lookupInstalledPackage :: DynFlags -> InstalledUnitId -> Maybe PackageConfig +lookupInstalledPackage dflags uid = lookupInstalledPackage' (pkgIdMap (pkgState dflags)) uid + +lookupInstalledPackage' :: PackageConfigMap -> InstalledUnitId -> Maybe PackageConfig +lookupInstalledPackage' (PackageConfigMap db _) uid = lookupUDFM db uid + +getInstalledPackageDetails :: DynFlags -> InstalledUnitId -> PackageConfig +getInstalledPackageDetails dflags uid = + expectJust "getInstalledPackageDetails" $ + lookupInstalledPackage dflags uid + -- | Get a list of entries from the package database. NB: be careful with -- this function, although all packages in this map are "visible", this -- does not imply that the exposed-modules of the package are available @@ -419,7 +443,7 @@ getPackageDetails dflags pid = listPackageConfigMap :: DynFlags -> [PackageConfig] listPackageConfigMap dflags = eltsUDFM pkg_map where - PackageConfigMap pkg_map = pkgIdMap (pkgState dflags) + PackageConfigMap pkg_map _ = pkgIdMap (pkgState dflags) -- ---------------------------------------------------------------------------- -- Loading the package db files and building up the package state @@ -437,7 +461,7 @@ listPackageConfigMap dflags = eltsUDFM pkg_map -- 'packageFlags' field of the 'DynFlags', and it will update the -- 'pkgState' in 'DynFlags' and return a list of packages to -- link in. -initPackages :: DynFlags -> IO (DynFlags, [UnitId]) +initPackages :: DynFlags -> IO (DynFlags, [PreloadUnitId]) initPackages dflags0 = do dflags <- interpretPackageEnv dflags0 pkg_db <- @@ -741,7 +765,7 @@ findPackages pkg_db arg pkgs unusable else Nothing finder (UnitIdArg uid) p = let (iuid, mb_insts) = splitUnitIdInsts uid - in if iuid == packageConfigId p + in if iuid == installedPackageConfigId p then Just (case mb_insts of Nothing -> p Just insts -> renamePackage pkg_db insts p) @@ -765,12 +789,10 @@ renamePackage :: PackageConfigMap -> [(ModuleName, Module)] -> PackageConfig -> PackageConfig renamePackage pkg_map insts conf = let hsubst = listToUFM insts - smod = renameHoleModule' pkg_map hsubst - suid = renameHoleUnitId' pkg_map hsubst - new_uid = suid (unitId conf) + smod = renameHoleModule' pkg_map hsubst + new_insts = map (\(k,v) -> (k,smod v)) (instantiatedWith conf) in conf { - unitId = new_uid, - depends = map suid (depends conf), + instantiatedWith = new_insts, exposedModules = map (\(mod_name, mb_mod) -> (mod_name, fmap smod mb_mod)) (exposedModules conf) } @@ -783,12 +805,13 @@ matchingStr str p = str == sourcePackageIdString p || str == packageNameString p -matchingId :: UnitId -> PackageConfig -> Bool -matchingId uid p = uid == packageConfigId p +matchingId :: InstalledUnitId -> PackageConfig -> Bool +matchingId uid p = uid == installedPackageConfigId p matching :: PackageArg -> PackageConfig -> Bool matching (PackageArg str) = matchingStr str -matching (UnitIdArg uid) = matchingId uid +matching (UnitIdArg (DefiniteUnitId (DefUnitId uid))) = matchingId uid +matching (UnitIdArg _) = \_ -> False -- TODO: warn in this case sortByVersion :: [PackageConfig] -> [PackageConfig] sortByVersion = sortBy (flip (comparing packageVersion)) @@ -849,7 +872,7 @@ pprTrustFlag flag = case flag of wired_in_pkgids :: [String] wired_in_pkgids = map unitIdString wiredInUnitIds -type WiredPackagesMap = Map UnitId UnitId +type WiredPackagesMap = Map WiredUnitId WiredUnitId findWiredInPackages :: DynFlags @@ -918,7 +941,7 @@ findWiredInPackages dflags pkgs vis_map = do mb_wired_in_pkgs <- mapM (findWiredInPackage pkgs) wired_in_pkgids let wired_in_pkgs = catMaybes mb_wired_in_pkgs - wired_in_ids = map unitId wired_in_pkgs + wired_in_ids = mapMaybe definitePackageConfigId wired_in_pkgs -- this is old: we used to assume that if there were -- multiple versions of wired-in packages installed that @@ -933,30 +956,38 @@ findWiredInPackages dflags pkgs vis_map = do && package p `notElem` map fst wired_in_ids -} - wiredInMap :: Map UnitId UnitId + wiredInMap :: Map WiredUnitId WiredUnitId wiredInMap = foldl' add_mapping Map.empty pkgs where add_mapping m pkg - | let key = unitId pkg + | Just key <- definitePackageConfigId pkg , key `elem` wired_in_ids - = Map.insert key (stringToUnitId (packageNameString pkg)) m + = Map.insert key (DefUnitId (stringToInstalledUnitId (packageNameString pkg))) m | otherwise = m updateWiredInDependencies pkgs = map (upd_deps . upd_pkg) pkgs where upd_pkg pkg - | unitId pkg `elem` wired_in_ids + | Just def_uid <- definitePackageConfigId pkg + , def_uid `elem` wired_in_ids = pkg { unitId = let PackageName fs = packageName pkg - in fsToUnitId fs + in fsToInstalledUnitId fs } | otherwise = pkg upd_deps pkg = pkg { - depends = map upd_wired_in (depends pkg), + -- temporary harmless DefUnitId invariant violation + depends = map (unDefUnitId . upd_wired_in . DefUnitId) (depends pkg), exposedModules = map (\(k,v) -> (k, fmap upd_wired_in_mod v)) (exposedModules pkg) } - upd_wired_in_mod (Module uid m) = Module (upd_wired_in uid) m + upd_wired_in_mod (Module uid m) = Module (upd_wired_in_uid uid) m + upd_wired_in_uid (DefiniteUnitId def_uid) = + DefiniteUnitId (upd_wired_in def_uid) + upd_wired_in_uid (IndefiniteUnitId indef_uid) = + IndefiniteUnitId $ newIndefUnitId + (indefUnitIdComponentId indef_uid) + (map (\(x,y) -> (x,upd_wired_in_mod y)) (indefUnitIdInsts indef_uid)) upd_wired_in key | Just key' <- Map.lookup key wiredInMap = key' | otherwise = key @@ -966,9 +997,10 @@ findWiredInPackages dflags pkgs vis_map = do updateVisibilityMap :: WiredPackagesMap -> VisibilityMap -> VisibilityMap updateVisibilityMap wiredInMap vis_map = foldl' f vis_map (Map.toList wiredInMap) - where f vm (from, to) = case Map.lookup from vis_map of + where f vm (from, to) = case Map.lookup (DefiniteUnitId from) vis_map of Nothing -> vm - Just r -> Map.insert to r (Map.delete from vm) + Just r -> Map.insert (DefiniteUnitId to) r + (Map.delete (DefiniteUnitId from) vm) -- ---------------------------------------------------------------------------- @@ -976,13 +1008,13 @@ updateVisibilityMap wiredInMap vis_map = foldl' f vis_map (Map.toList wiredInMap type IsShadowed = Bool data UnusablePackageReason = IgnoredWithFlag - | MissingDependencies IsShadowed [UnitId] + | MissingDependencies IsShadowed [InstalledUnitId] instance Outputable UnusablePackageReason where ppr IgnoredWithFlag = text "[ignored with flag]" ppr (MissingDependencies b uids) = brackets (if b then text "shadowed" else empty <+> ppr uids) -type UnusablePackages = Map UnitId +type UnusablePackages = Map InstalledUnitId (PackageConfig, UnusablePackageReason) pprReason :: SDoc -> UnusablePackageReason -> SDoc @@ -1014,7 +1046,7 @@ reportUnusable dflags pkgs = mapM_ report (Map.toList pkgs) -- findBroken :: IsShadowed -> [PackageConfig] - -> Map UnitId PackageConfig + -> Map InstalledUnitId PackageConfig -> UnusablePackages findBroken is_shadowed pkgs pkg_map0 = go [] pkg_map0 pkgs where @@ -1031,7 +1063,7 @@ findBroken is_shadowed pkgs pkg_map0 = go [] pkg_map0 pkgs depsAvailable :: InstalledPackageIndex -> PackageConfig - -> Either PackageConfig (PackageConfig, [UnitId]) + -> Either PackageConfig (PackageConfig, [InstalledUnitId]) depsAvailable pkg_map pkg | null dangling = Left pkg | otherwise = Right (pkg, dangling) @@ -1058,9 +1090,9 @@ ignorePackages flags pkgs = Map.fromList (concatMap doit flags) mkPackageState :: DynFlags -> [(FilePath, [PackageConfig])] -- initial databases - -> [UnitId] -- preloaded packages + -> [PreloadUnitId] -- preloaded packages -> IO (PackageState, - [UnitId]) -- new packages to preload + [PreloadUnitId]) -- new packages to preload mkPackageState dflags dbs preload0 = do -- Compute the unit id @@ -1138,7 +1170,7 @@ mkPackageState dflags dbs preload0 = do `Map.union` unusable) where -- The set of UnitIds which appear in both -- db and pkgs (to be shadowed from pkgs) - shadow_set :: Set UnitId + shadow_set :: Set InstalledUnitId shadow_set = foldr ins Set.empty db where ins pkg s -- If the package from the upper database is @@ -1180,7 +1212,7 @@ mkPackageState dflags dbs preload0 = do -- Now merge the sets together (NB: later overrides -- earlier!) - pkg_map' :: Map UnitId PackageConfig + pkg_map' :: Map InstalledUnitId PackageConfig pkg_map' = mk_pkg_map (shadowed_pkgs ++ db3) (pkg_map1, unusable) <- foldM merge (Map.empty, Map.empty) dbs @@ -1309,7 +1341,7 @@ mkPackageState dflags dbs preload0 = do $ (basicLinkedPackages ++ preload2) -- Close the preload packages with their dependencies - dep_preload <- closeDeps dflags pkg_db (zip preload3 (repeat Nothing)) + dep_preload <- closeDeps dflags pkg_db (zip (map toInstalledUnitId preload3) (repeat Nothing)) let new_dep_preload = filter (`notElem` preload0) dep_preload let mod_map = mkModuleToPkgConfAll dflags pkg_db vis_map @@ -1333,8 +1365,9 @@ mkPackageState dflags dbs preload0 = do -- | Given a wired-in 'UnitId', "unwire" it into the 'UnitId' -- that it was recorded as in the package database. unwireUnitId :: DynFlags -> UnitId -> UnitId -unwireUnitId dflags uid = - fromMaybe uid (Map.lookup uid (unwireMap (pkgState dflags))) +unwireUnitId dflags uid@(DefiniteUnitId def_uid) = + maybe uid DefiniteUnitId (Map.lookup def_uid (unwireMap (pkgState dflags))) +unwireUnitId _ uid = uid -- ----------------------------------------------------------------------------- -- | Makes the mapping from module to package info @@ -1415,7 +1448,7 @@ mkModuleToPkgConfAll dflags pkg_db vis_map = -- use. -- | Find all the include directories in these and the preload packages -getPackageIncludePath :: DynFlags -> [UnitId] -> IO [String] +getPackageIncludePath :: DynFlags -> [PreloadUnitId] -> IO [String] getPackageIncludePath dflags pkgs = collectIncludeDirs `fmap` getPreloadPackagesAnd dflags pkgs @@ -1423,7 +1456,7 @@ collectIncludeDirs :: [PackageConfig] -> [FilePath] collectIncludeDirs ps = nub (filter notNull (concatMap includeDirs ps)) -- | Find all the library paths in these and the preload packages -getPackageLibraryPath :: DynFlags -> [UnitId] -> IO [String] +getPackageLibraryPath :: DynFlags -> [PreloadUnitId] -> IO [String] getPackageLibraryPath dflags pkgs = collectLibraryPaths `fmap` getPreloadPackagesAnd dflags pkgs @@ -1432,7 +1465,7 @@ collectLibraryPaths ps = nub (filter notNull (concatMap libraryDirs ps)) -- | Find all the link options in these and the preload packages, -- returning (package hs lib options, extra library options, other flags) -getPackageLinkOpts :: DynFlags -> [UnitId] -> IO ([String], [String], [String]) +getPackageLinkOpts :: DynFlags -> [PreloadUnitId] -> IO ([String], [String], [String]) getPackageLinkOpts dflags pkgs = collectLinkOpts dflags `fmap` getPreloadPackagesAnd dflags pkgs @@ -1481,19 +1514,19 @@ packageHsLibs dflags p = map (mkDynName . addSuffix) (hsLibraries p) | otherwise = '_':t -- | Find all the C-compiler options in these and the preload packages -getPackageExtraCcOpts :: DynFlags -> [UnitId] -> IO [String] +getPackageExtraCcOpts :: DynFlags -> [PreloadUnitId] -> IO [String] getPackageExtraCcOpts dflags pkgs = do ps <- getPreloadPackagesAnd dflags pkgs return (concatMap ccOptions ps) -- | Find all the package framework paths in these and the preload packages -getPackageFrameworkPath :: DynFlags -> [UnitId] -> IO [String] +getPackageFrameworkPath :: DynFlags -> [PreloadUnitId] -> IO [String] getPackageFrameworkPath dflags pkgs = do ps <- getPreloadPackagesAnd dflags pkgs return (nub (filter notNull (concatMap frameworkDirs ps))) -- | Find all the package frameworks in these and the preload packages -getPackageFrameworks :: DynFlags -> [UnitId] -> IO [String] +getPackageFrameworks :: DynFlags -> [PreloadUnitId] -> IO [String] getPackageFrameworks dflags pkgs = do ps <- getPreloadPackagesAnd dflags pkgs return (concatMap frameworks ps) @@ -1616,7 +1649,7 @@ listVisibleModuleNames dflags = -- | Find all the 'PackageConfig' in both the preload packages from 'DynFlags' and corresponding to the list of -- 'PackageConfig's -getPreloadPackagesAnd :: DynFlags -> [UnitId] -> IO [PackageConfig] +getPreloadPackagesAnd :: DynFlags -> [PreloadUnitId] -> IO [PackageConfig] getPreloadPackagesAnd dflags pkgids = let state = pkgState dflags @@ -1625,14 +1658,14 @@ getPreloadPackagesAnd dflags pkgids = pairs = zip pkgids (repeat Nothing) in do all_pkgs <- throwErr dflags (foldM (add_package dflags pkg_map) preload pairs) - return (map (getPackageDetails dflags) all_pkgs) + return (map (getInstalledPackageDetails dflags) all_pkgs) -- Takes a list of packages, and returns the list with dependencies included, -- in reverse dependency order (a package appears before those it depends on). closeDeps :: DynFlags -> PackageConfigMap - -> [(UnitId, Maybe UnitId)] - -> IO [UnitId] + -> [(InstalledUnitId, Maybe InstalledUnitId)] + -> IO [InstalledUnitId] closeDeps dflags pkg_map ps = throwErr dflags (closeDepsErr dflags pkg_map ps) @@ -1644,20 +1677,20 @@ throwErr dflags m closeDepsErr :: DynFlags -> PackageConfigMap - -> [(UnitId,Maybe UnitId)] - -> MaybeErr MsgDoc [UnitId] + -> [(InstalledUnitId,Maybe InstalledUnitId)] + -> MaybeErr MsgDoc [InstalledUnitId] closeDepsErr dflags pkg_map ps = foldM (add_package dflags pkg_map) [] ps -- internal helper add_package :: DynFlags -> PackageConfigMap - -> [UnitId] - -> (UnitId,Maybe UnitId) - -> MaybeErr MsgDoc [UnitId] + -> [PreloadUnitId] + -> (PreloadUnitId,Maybe PreloadUnitId) + -> MaybeErr MsgDoc [PreloadUnitId] add_package dflags pkg_db ps (p, mb_parent) | p `elem` ps = return ps -- Check if we've already added this package | otherwise = - case lookupPackage' (isIndefinite dflags) pkg_db p of + case lookupInstalledPackage' pkg_db p of Nothing -> Failed (missingPackageMsg p <> missingDependencyMsg mb_parent) Just pkg -> do @@ -1671,19 +1704,19 @@ add_package dflags pkg_db ps (p, mb_parent) missingPackageMsg :: Outputable pkgid => pkgid -> SDoc missingPackageMsg p = text "unknown package:" <+> ppr p -missingDependencyMsg :: Maybe UnitId -> SDoc +missingDependencyMsg :: Maybe InstalledUnitId -> SDoc missingDependencyMsg Nothing = Outputable.empty missingDependencyMsg (Just parent) - = space <> parens (text "dependency of" <+> ftext (unitIdFS parent)) + = space <> parens (text "dependency of" <+> ftext (installedUnitIdFS parent)) -- ----------------------------------------------------------------------------- componentIdString :: DynFlags -> ComponentId -> Maybe String componentIdString dflags cid = - fmap sourcePackageIdString (lookupComponentId dflags cid) + fmap sourcePackageIdString (lookupInstalledPackage dflags (newInstalledUnitId cid Nothing)) -- | Will the 'Name' come from a dynamically linked library? -isDllName :: DynFlags -> UnitId -> Module -> Name -> Bool +isDllName :: DynFlags -> UnitId {- not used -} -> Module -> Name -> Bool -- Despite the "dll", I think this function just means that -- the symbol comes from another dynamically-linked package, -- and applies on all platforms, not just Windows @@ -1732,7 +1765,7 @@ pprPackagesWith pprIPI dflags = -- be different from the package databases (exposure, trust) pprPackagesSimple :: DynFlags -> SDoc pprPackagesSimple = pprPackagesWith pprIPI - where pprIPI ipi = let i = unitIdFS (unitId ipi) + where pprIPI ipi = let i = installedUnitIdFS (unitId ipi) e = if exposed ipi then text "E" else text " " t = if trusted ipi then text "T" else text " " in e <> t <> text " " <> ftext i @@ -1752,13 +1785,20 @@ fsPackageName :: PackageConfig -> FastString fsPackageName = mkFastString . packageNameString -- | Given a fully instantiated 'UnitId', improve it into a --- 'HashedUnitId' if we can find it in the package database. +-- 'InstalledUnitId' if we can find it in the package database. improveUnitId :: PackageConfigMap -> UnitId -> UnitId +improveUnitId _ uid@(DefiniteUnitId _) = uid -- short circuit improveUnitId pkg_map uid = -- Do NOT lookup indefinite ones, they won't be useful! case lookupPackage' False pkg_map uid of Nothing -> uid - Just pkg -> packageConfigId pkg -- use the hashed version! + Just pkg -> + -- Do NOT improve if the indefinite unit id is not + -- part of the closure unique set. See + -- Note [UnitId to InstalledUnitId improvement] + if installedPackageConfigId pkg `elementOfUniqSet` preloadClosure pkg_map + then packageConfigId pkg + else uid -- | Retrieve the 'PackageConfigMap' from 'DynFlags'; used -- in the @hs-boot@ loop-breaker. diff --git a/compiler/main/SysTools.hs b/compiler/main/SysTools.hs index e40b1d679f..e901bde06e 100644 --- a/compiler/main/SysTools.hs +++ b/compiler/main/SysTools.hs @@ -1564,7 +1564,7 @@ linesPlatform xs = #endif -linkDynLib :: DynFlags -> [String] -> [UnitId] -> IO () +linkDynLib :: DynFlags -> [String] -> [InstalledUnitId] -> IO () linkDynLib dflags0 o_files dep_packages = do let -- This is a rather ugly hack to fix dynamically linked @@ -1741,7 +1741,7 @@ linkDynLib dflags0 o_files dep_packages ++ map Option pkg_link_opts ) -getPkgFrameworkOpts :: DynFlags -> Platform -> [UnitId] -> IO [String] +getPkgFrameworkOpts :: DynFlags -> Platform -> [InstalledUnitId] -> IO [String] getPkgFrameworkOpts dflags platform dep_packages | platformUsesFrameworks platform = do pkg_framework_path_opts <- do |