summaryrefslogtreecommitdiff
path: root/compiler/GHC/Iface/Recomp.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Iface/Recomp.hs')
-rw-r--r--compiler/GHC/Iface/Recomp.hs119
1 files changed, 27 insertions, 92 deletions
diff --git a/compiler/GHC/Iface/Recomp.hs b/compiler/GHC/Iface/Recomp.hs
index e033a6628a..9bccffab3d 100644
--- a/compiler/GHC/Iface/Recomp.hs
+++ b/compiler/GHC/Iface/Recomp.hs
@@ -63,9 +63,8 @@ import GHC.Unit.Module.Deps
import Control.Monad
import Data.Function
-import Data.List (find, sortBy, sort)
+import Data.List (sortBy, sort)
import qualified Data.Map as Map
-import qualified Data.Set as Set
import Data.Word (Word64)
--Qualified import so we can define a Semigroup instance
@@ -265,11 +264,10 @@ checkVersions hsc_env mod_summary iface
-- It's just temporary because either the usage check will succeed
-- (in which case we are done with this module) or it'll fail (in which
-- case we'll compile the module from scratch anyhow).
- --
- -- We do this regardless of compilation mode, although in --make mode
- -- all the dependent modules should be in the HPT already, so it's
- -- quite redundant
- ; updateEps_ $ \eps -> eps { eps_is_boot = mod_deps }
+
+ when (isOneShot (ghcMode (hsc_dflags hsc_env))) $ do {
+ ; updateEps_ $ \eps -> eps { eps_is_boot = mkModDeps $ (dep_boot_mods (mi_deps iface)) }
+ }
; recomp <- checkList [checkModUsage (homeUnitAsUnit home_unit) u
| u <- mi_usages iface]
; return (recomp, Just iface)
@@ -278,9 +276,9 @@ checkVersions hsc_env mod_summary iface
logger = hsc_logger hsc_env
dflags = hsc_dflags hsc_env
home_unit = hsc_home_unit hsc_env
- -- This is a bit of a hack really
- mod_deps :: ModuleNameEnv ModuleNameWithIsBoot
- mod_deps = mkModDeps (dep_mods (mi_deps iface))
+
+
+
-- | Check if any plugins are requesting recompilation
checkPlugins :: HscEnv -> ModIface -> IfG RecompileRequired
@@ -450,38 +448,19 @@ checkMergedSignatures hsc_env mod_summary iface = do
-- - a new home module has been added that shadows a package module
-- See bug #1372.
--
--- In addition, we also check if the union of dependencies of the imported
--- modules has any difference to the previous set of dependencies. We would need
--- to recompile in that case also since the `mi_deps` field of ModIface needs
--- to be updated to match that information. This is one of the invariants
--- of interface files (see https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance#interface-file-invariants).
--- See bug #16511.
---
-- Returns (RecompBecause <textual reason>) if recompilation is required.
checkDependencies :: HscEnv -> ModSummary -> ModIface -> IfG RecompileRequired
checkDependencies hsc_env summary iface
- =
- checkList $
- [ liftIO $ checkList (map dep_missing (ms_imps summary ++ ms_srcimps summary))
- , do
- (recomp, mnames_seen) <- runUntilRecompRequired $ map
- checkForNewHomeDependency
- (ms_home_imps summary)
- liftIO $ case recomp of
- UpToDate -> do
- let
- seen_home_deps = Set.unions $ map Set.fromList mnames_seen
- checkIfAllOldHomeDependenciesAreSeen seen_home_deps
- _ -> return recomp]
+ = liftIO $ checkList (map dep_missing (ms_imps summary ++ ms_srcimps summary))
where
dflags = hsc_dflags hsc_env
logger = hsc_logger hsc_env
fc = hsc_FC hsc_env
home_unit = hsc_home_unit hsc_env
units = hsc_units hsc_env
- prev_dep_mods = dep_mods (mi_deps iface)
+ prev_dep_mods = dep_direct_mods (mi_deps iface)
prev_dep_plgn = dep_plgins (mi_deps iface)
- prev_dep_pkgs = dep_pkgs (mi_deps iface)
+ prev_dep_pkgs = dep_direct_pkgs (mi_deps iface)
dep_missing (mb_pkg, L _ mod) = do
find_res <- findImportedModule fc units home_unit dflags mod (mb_pkg)
@@ -497,7 +476,7 @@ checkDependencies hsc_env summary iface
else
return UpToDate
| otherwise
- -> if toUnitId pkg `notElem` (map fst prev_dep_pkgs)
+ -> if toUnitId pkg `notElem` prev_dep_pkgs
then do trace_hi_diffs logger dflags $
text "imported module " <> quotes (ppr mod) <>
text " is from package " <> quotes (ppr pkg) <>
@@ -508,58 +487,6 @@ checkDependencies hsc_env summary iface
where pkg = moduleUnit mod
_otherwise -> return (RecompBecause reason)
- projectNonBootNames = map gwib_mod . filter ((== NotBoot) . gwib_isBoot)
- old_deps = Set.fromList
- $ projectNonBootNames prev_dep_mods
- isOldHomeDeps = flip Set.member old_deps
- checkForNewHomeDependency (L _ mname) = do
- let
- mod = mkHomeModule home_unit mname
- str_mname = moduleNameString mname
- reason = str_mname ++ " changed"
- -- We only want to look at home modules to check if any new home dependency
- -- pops in and thus here, skip modules that are not home. Checking
- -- membership in old home dependencies suffice because the `dep_missing`
- -- check already verified that all imported home modules are present there.
- if not (isOldHomeDeps mname)
- then return (UpToDate, [])
- else do
- mb_result <- getFromModIface "need mi_deps for" mod $ \imported_iface -> do
- let mnames = mname:(map gwib_mod $ filter ((== NotBoot) . gwib_isBoot) $
- dep_mods $ mi_deps imported_iface)
- case find (not . isOldHomeDeps) mnames of
- Nothing -> return (UpToDate, mnames)
- Just new_dep_mname -> do
- trace_hi_diffs logger dflags $
- text "imported home module " <> quotes (ppr mod) <>
- text " has a new dependency " <> quotes (ppr new_dep_mname)
- return (RecompBecause reason, [])
- return $ fromMaybe (MustCompile, []) mb_result
-
- -- Performs all recompilation checks in the list until a check that yields
- -- recompile required is encountered. Returns the list of the results of
- -- all UpToDate checks.
- runUntilRecompRequired [] = return (UpToDate, [])
- runUntilRecompRequired (check:checks) = do
- (recompile, value) <- check
- if recompileRequired recompile
- then return (recompile, [])
- else do
- (recomp, values) <- runUntilRecompRequired checks
- return (recomp, value:values)
-
- checkIfAllOldHomeDependenciesAreSeen seen_deps = do
- let unseen_old_deps = Set.difference
- old_deps
- seen_deps
- if not (null unseen_old_deps)
- then do
- let missing_dep = Set.elemAt 0 unseen_old_deps
- trace_hi_diffs logger dflags $
- text "missing old home dependency " <> quotes (ppr missing_dep)
- return $ RecompBecause "missing old dependency"
- else return UpToDate
-
needInterface :: Module -> (ModIface -> IO RecompileRequired)
-> IfG RecompileRequired
needInterface mod continue
@@ -1043,17 +970,22 @@ addFingerprints hsc_env iface0
orphan_hash <- computeFingerprint (mk_put_name local_env)
(map ifDFun orph_insts, orph_rules, orph_fis)
+ -- Hash of the transitive things in dependencies
+ dep_hash <- computeFingerprint putNameLiterally
+ (dep_sig_mods (mi_deps iface0),
+ dep_boot_mods (mi_deps iface0),
+ -- Trusted packages are like orphans
+ dep_trusted_pkgs (mi_deps iface0),
+ -- See Note [Export hash depends on non-orphan family instances]
+ dep_finsts (mi_deps iface0) )
+
-- the export list hash doesn't depend on the fingerprints of
-- the Names it mentions, only the Names themselves, hence putNameLiterally.
export_hash <- computeFingerprint putNameLiterally
(mi_exports iface0,
orphan_hash,
+ dep_hash,
dep_orphan_hashes,
- dep_pkgs (mi_deps iface0),
- -- See Note [Export hash depends on non-orphan family instances]
- dep_finsts (mi_deps iface0),
- -- dep_pkgs: see "Package Version Changes" on
- -- wiki/commentary/compiler/recompilation-avoidance
mi_trust iface0)
-- Make sure change of Safe Haskell mode causes recomp.
@@ -1209,8 +1141,11 @@ getOrphanHashes hsc_env mods = do
sortDependencies :: Dependencies -> Dependencies
sortDependencies d
- = Deps { dep_mods = sortBy (lexicalCompareFS `on` (moduleNameFS . gwib_mod)) (dep_mods d),
- dep_pkgs = sortBy (compare `on` fst) (dep_pkgs d),
+ = Deps { dep_direct_mods = sortBy (lexicalCompareFS `on` (moduleNameFS . gwib_mod)) (dep_direct_mods d),
+ dep_direct_pkgs = sort (dep_direct_pkgs d),
+ dep_sig_mods = sort (dep_sig_mods d),
+ dep_trusted_pkgs = sort (dep_trusted_pkgs d),
+ dep_boot_mods = sort (dep_boot_mods d),
dep_orphs = sortBy stableModuleCmp (dep_orphs d),
dep_finsts = sortBy stableModuleCmp (dep_finsts d),
dep_plgins = sortBy (lexicalCompareFS `on` moduleNameFS) (dep_plgins d) }