summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2020-04-30 11:07:15 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-06-04 04:34:42 -0400
commit32a4ae90b50cc56f2955f489ad0cf8c7ff5e131a (patch)
tree274e86d49420a09eb8400bc3751c55f827ed4e56 /compiler
parentcb5c31b51b021ce86890bba73276fe6f7405f5d3 (diff)
downloadhaskell-32a4ae90b50cc56f2955f489ad0cf8c7ff5e131a.tar.gz
Clean up boot vs non-boot disambiguating types
We often have (ModuleName, Bool) or (Module, Bool) pairs for "extended" module names (without or with a unit id) disambiguating boot and normal modules. We think this is important enough across the compiler that it deserves a new nominal product type. We do this with synnoyms and a functor named with a `Gen` prefix, matching other newly created definitions. It was also requested that we keep custom `IsBoot` / `NotBoot` sum type. So we have it too. This means changing many the many bools to use that instead. Updates `haddock` submodule.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/GHC.hs2
-rw-r--r--compiler/GHC/Driver/Backpack.hs2
-rw-r--r--compiler/GHC/Driver/Make.hs177
-rw-r--r--compiler/GHC/Driver/MakeFile.hs4
-rw-r--r--compiler/GHC/Driver/Types.hs45
-rw-r--r--compiler/GHC/Hs/ImpExp.hs10
-rw-r--r--compiler/GHC/HsToCore/Monad.hs2
-rw-r--r--compiler/GHC/HsToCore/Usage.hs7
-rw-r--r--compiler/GHC/Iface/Load.hs26
-rw-r--r--compiler/GHC/Iface/Recomp.hs12
-rw-r--r--compiler/GHC/IfaceToCore.hs28
-rw-r--r--compiler/GHC/Parser.y14
-rw-r--r--compiler/GHC/Parser/Header.hs4
-rw-r--r--compiler/GHC/Rename/Env.hs2
-rw-r--r--compiler/GHC/Rename/Names.hs28
-rw-r--r--compiler/GHC/Runtime/Linker.hs13
-rw-r--r--compiler/GHC/Tc/Module.hs4
-rw-r--r--compiler/GHC/Tc/Types.hs27
-rw-r--r--compiler/GHC/Tc/Utils/Backpack.hs8
-rw-r--r--compiler/GHC/Tc/Utils/Monad.hs6
-rw-r--r--compiler/GHC/Unit/Module.hs12
-rw-r--r--compiler/GHC/Unit/Module/Location.hs9
-rw-r--r--compiler/GHC/Unit/Types.hs70
23 files changed, 316 insertions, 196 deletions
diff --git a/compiler/GHC.hs b/compiler/GHC.hs
index 759dda29e6..442fd0a323 100644
--- a/compiler/GHC.hs
+++ b/compiler/GHC.hs
@@ -936,7 +936,7 @@ getModSummary mod = do
mg <- liftM hsc_mod_graph getSession
let mods_by_name = [ ms | ms <- mgModSummaries mg
, ms_mod_name ms == mod
- , not (isBootSummary ms) ]
+ , isBootSummary ms == NotBoot ]
case mods_by_name of
[] -> do dflags <- getDynFlags
liftIO $ throwIO $ mkApiErr dflags (text "Module not part of module graph")
diff --git a/compiler/GHC/Driver/Backpack.hs b/compiler/GHC/Driver/Backpack.hs
index 7bae489f22..5d5be6c1ff 100644
--- a/compiler/GHC/Driver/Backpack.hs
+++ b/compiler/GHC/Driver/Backpack.hs
@@ -772,7 +772,7 @@ hsModuleToModSummary pn hsc_src modname
hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file location)
-- Also copied from 'getImports'
- let (src_idecls, ord_idecls) = partition (ideclSource.unLoc) imps
+ let (src_idecls, ord_idecls) = partition ((== IsBoot) . ideclSource . unLoc) imps
-- GHC.Prim doesn't exist physically, so don't go looking for it.
ordinary_imps = filter ((/= moduleName gHC_PRIM) . unLoc . ideclName . unLoc)
diff --git a/compiler/GHC/Driver/Make.hs b/compiler/GHC/Driver/Make.hs
index 43c988c4c2..a3d2c0b1bb 100644
--- a/compiler/GHC/Driver/Make.hs
+++ b/compiler/GHC/Driver/Make.hs
@@ -21,14 +21,14 @@ module GHC.Driver.Make (
ms_home_srcimps, ms_home_imps,
- IsBoot(..),
summariseModule,
hscSourceToIsBoot,
findExtraSigImports,
implicitRequirements,
noModError, cyclicModuleErr,
- moduleGraphNodes, SummaryNode
+ moduleGraphNodes, SummaryNode,
+ IsBootInterface(..)
) where
#include "HsVersions.h"
@@ -378,7 +378,7 @@ load' how_much mHscMessage mod_graph = do
-- (see msDeps)
let all_home_mods =
mkUniqSet [ ms_mod_name s
- | s <- mgModSummaries mod_graph, not (isBootSummary s)]
+ | s <- mgModSummaries mod_graph, isBootSummary s == NotBoot]
-- TODO: Figure out what the correct form of this assert is. It's violated
-- when you have HsBootMerge nodes in the graph: then you'll have hs-boot
-- files without corresponding hs files.
@@ -930,23 +930,26 @@ buildCompGraph (scc:sccs) = case scc of
return ((ms,mvar,log_queue):rest, cycle)
CyclicSCC mss -> return ([], Just mss)
--- A Module and whether it is a boot module.
-type BuildModule = (Module, IsBoot)
-
--- | 'Bool' indicating if a module is a boot module or not. We need to treat
--- boot modules specially when building compilation graphs, since they break
--- cycles. Regular source files and signature files are treated equivalently.
-data IsBoot = NotBoot | IsBoot
- deriving (Ord, Eq, Show, Read)
-
--- | Tests if an 'HscSource' is a boot file, primarily for constructing
--- elements of 'BuildModule'.
-hscSourceToIsBoot :: HscSource -> IsBoot
+-- | A Module and whether it is a boot module.
+--
+-- We need to treat boot modules specially when building compilation graphs,
+-- since they break cycles. Regular source files and signature files are treated
+-- equivalently.
+type BuildModule = ModuleWithIsBoot
+
+-- | Tests if an 'HscSource' is a boot file, primarily for constructing elements
+-- of 'BuildModule'. We conflate signatures and modules because they are bound
+-- in the same namespace; only boot interfaces can be disambiguated with
+-- `import {-# SOURCE #-}`.
+hscSourceToIsBoot :: HscSource -> IsBootInterface
hscSourceToIsBoot HsBootFile = IsBoot
hscSourceToIsBoot _ = NotBoot
mkBuildModule :: ModSummary -> BuildModule
-mkBuildModule ms = (ms_mod ms, if isBootSummary ms then IsBoot else NotBoot)
+mkBuildModule ms = GWIB
+ { gwib_mod = ms_mod ms
+ , gwib_isBoot = isBootSummary ms
+ }
-- | The entry point to the parallel upsweep.
--
@@ -1014,12 +1017,12 @@ parUpsweep n_jobs mHscMessage old_hpt stable_mods cleanup sccs = do
-- NB: For convenience, the last module of each loop (aka the module that
-- finishes the loop) is prepended to the beginning of the loop.
let graph = map fstOf3 (reverse comp_graph)
- boot_modules = mkModuleSet [ms_mod ms | ms <- graph, isBootSummary ms]
+ boot_modules = mkModuleSet [ms_mod ms | ms <- graph, isBootSummary ms == IsBoot]
comp_graph_loops = go graph boot_modules
where
- remove ms bm
- | isBootSummary ms = delModuleSet bm (ms_mod ms)
- | otherwise = bm
+ remove ms bm = case isBootSummary ms of
+ IsBoot -> delModuleSet bm (ms_mod ms)
+ NotBoot -> bm
go [] _ = []
go mg@(ms:mss) boot_modules
| Just loop <- getModLoop ms mg (`elemModuleSet` boot_modules)
@@ -1193,9 +1196,13 @@ parUpsweep_one mod home_mod_map comp_graph_loops lcl_dflags mHscMessage cleanup
let home_src_imps = map unLoc $ ms_home_srcimps mod
-- All the textual imports of this module.
- let textual_deps = Set.fromList $ mapFst (mkModule (thisPackage lcl_dflags)) $
- zip home_imps (repeat NotBoot) ++
- zip home_src_imps (repeat IsBoot)
+ let textual_deps = Set.fromList $
+ zipWith f home_imps (repeat NotBoot) ++
+ zipWith f home_src_imps (repeat IsBoot)
+ where f mn isBoot = GWIB
+ { gwib_mod = mkModule (thisPackage lcl_dflags) mn
+ , gwib_isBoot = isBoot
+ }
-- Dealing with module loops
-- ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1301,8 +1308,8 @@ parUpsweep_one mod home_mod_map comp_graph_loops lcl_dflags mHscMessage cleanup
-- SCCs include the loop closer, so we have to filter
-- it out.
Just loop -> typecheckLoop lcl_dflags lcl_hsc_env' $
- filter (/= moduleName (fst this_build_mod)) $
- map (moduleName . fst) loop
+ filter (/= moduleName (gwib_mod this_build_mod)) $
+ map (moduleName . gwib_mod) loop
-- Compile the module.
mod_info <- upsweep_mod lcl_hsc_env'' mHscMessage old_hpt stable_mods
@@ -1315,7 +1322,7 @@ parUpsweep_one mod home_mod_map comp_graph_loops lcl_dflags mHscMessage cleanup
let this_mod = ms_mod_name mod
-- Prune the old HPT unless this is an hs-boot module.
- unless (isBootSummary mod) $
+ unless (isBootSummary mod == IsBoot) $
atomicModifyIORef' old_hpt_var $ \old_hpt ->
(delFromHpt old_hpt this_mod, ())
@@ -1331,7 +1338,7 @@ parUpsweep_one mod home_mod_map comp_graph_loops lcl_dflags mHscMessage cleanup
hsc_env'' <- case finish_loop of
Nothing -> return hsc_env'
Just loop -> typecheckLoop lcl_dflags hsc_env' $
- map (moduleName . fst) loop
+ map (moduleName . gwib_mod) loop
return (hsc_env'', localize_hsc_env hsc_env'')
-- Clean up any intermediate files.
@@ -1491,8 +1498,9 @@ upsweep mHscMessage old_hpt stable_mods cleanup sccs = do
-- main Haskell source file. Deleting it
-- would force the real module to be recompiled
-- every time.
- old_hpt1 | isBootSummary mod = old_hpt
- | otherwise = delFromHpt old_hpt this_mod
+ old_hpt1 = case isBootSummary mod of
+ IsBoot -> old_hpt
+ NotBoot -> delFromHpt old_hpt this_mod
done' = extendMG done mod
@@ -1596,10 +1604,10 @@ upsweep_mod hsc_env mHscMessage old_hpt (stable_obj, stable_bco) summary mod_ind
mb_old_iface
= case old_hmi of
- Nothing -> Nothing
- Just hm_info | isBootSummary summary -> Just iface
- | not (mi_boot iface) -> Just iface
- | otherwise -> Nothing
+ Nothing -> Nothing
+ Just hm_info | isBootSummary summary == IsBoot -> Just iface
+ | mi_boot iface == NotBoot -> Just iface
+ | otherwise -> Nothing
where
iface = hm_iface hm_info
@@ -1823,7 +1831,7 @@ reTypecheckLoop hsc_env ms graph
| Just loop <- getModLoop ms mss appearsAsBoot
-- SOME hs-boot files should still
-- get used, just not the loop-closer.
- , let non_boot = filter (\l -> not (isBootSummary l &&
+ , let non_boot = filter (\l -> not (isBootSummary l == IsBoot &&
ms_mod l == ms_mod ms)) loop
= typecheckLoop (hsc_dflags hsc_env) hsc_env (map ms_mod_name non_boot)
| otherwise
@@ -1874,7 +1882,7 @@ getModLoop
-> (Module -> Bool) -- check if a module appears as a boot module in 'graph'
-> Maybe [ModSummary]
getModLoop ms graph appearsAsBoot
- | not (isBootSummary ms)
+ | isBootSummary ms == NotBoot
, appearsAsBoot this_mod
, let mss = reachableBackwards (ms_mod_name ms) graph
= Just mss
@@ -1974,14 +1982,23 @@ moduleGraphNodes drop_hs_boot_nodes summaries =
numbered_summaries = zip summaries [1..]
lookup_node :: HscSource -> ModuleName -> Maybe SummaryNode
- lookup_node hs_src mod = Map.lookup (mod, hscSourceToIsBoot hs_src) node_map
+ lookup_node hs_src mod = Map.lookup
+ GWIB
+ { gwib_mod = mod
+ , gwib_isBoot = hscSourceToIsBoot hs_src
+ }
+ node_map
lookup_key :: HscSource -> ModuleName -> Maybe Int
lookup_key hs_src mod = fmap summaryNodeKey (lookup_node hs_src mod)
node_map :: NodeMap SummaryNode
- node_map = Map.fromList [ ((moduleName (ms_mod s),
- hscSourceToIsBoot (ms_hsc_src s)), node)
+ node_map = Map.fromList [ ( GWIB
+ { gwib_mod = moduleName $ ms_mod s
+ , gwib_isBoot = hscSourceToIsBoot $ ms_hsc_src s
+ }
+ , node
+ )
| node <- nodes
, let s = summaryNodeSummary node ]
@@ -1990,7 +2007,7 @@ moduleGraphNodes drop_hs_boot_nodes summaries =
nodes = [ DigraphNode s key out_keys
| (s, key) <- numbered_summaries
-- Drop the hi-boot ones if told to do so
- , not (isBootSummary s && drop_hs_boot_nodes)
+ , not (isBootSummary s == IsBoot && drop_hs_boot_nodes)
, let out_keys = out_edge_keys hs_boot_key (map unLoc (ms_home_srcimps s)) ++
out_edge_keys HsSrcFile (map unLoc (ms_home_imps s)) ++
(-- see [boot-edges] below
@@ -2015,17 +2032,20 @@ moduleGraphNodes drop_hs_boot_nodes summaries =
out_edge_keys :: HscSource -> [ModuleName] -> [Int]
out_edge_keys hi_boot ms = mapMaybe (lookup_key hi_boot) ms
-- If we want keep_hi_boot_nodes, then we do lookup_key with
- -- IsBoot; else NotBoot
+ -- IsBoot; else False
-- The nodes of the graph are keyed by (mod, is boot?) pairs
-- NB: hsig files show up as *normal* nodes (not boot!), since they don't
-- participate in cycles (for now)
-type NodeKey = (ModuleName, IsBoot)
+type NodeKey = ModuleNameWithIsBoot
type NodeMap a = Map.Map NodeKey a
msKey :: ModSummary -> NodeKey
msKey (ModSummary { ms_mod = mod, ms_hsc_src = boot })
- = (moduleName mod, hscSourceToIsBoot boot)
+ = GWIB
+ { gwib_mod = moduleName mod
+ , gwib_isBoot = hscSourceToIsBoot boot
+ }
mkNodeMap :: [ModSummary] -> NodeMap ModSummary
mkNodeMap summaries = Map.fromList [ (msKey s, s) | s <- summaries]
@@ -2143,7 +2163,7 @@ downsweep hsc_env old_summaries excl_mods allow_dup_roots
dup_roots :: [[ModSummary]] -- Each at least of length 2
dup_roots = filterOut isSingleton $ map rights $ nodeMapElts root_map
- loop :: [(Located ModuleName,IsBoot)]
+ loop :: [GenWithIsBoot (Located ModuleName)]
-- Work list: process these modules
-> NodeMap [Either ErrorMessages ModSummary]
-- Visited set; the range is a list because
@@ -2152,7 +2172,7 @@ downsweep hsc_env old_summaries excl_mods allow_dup_roots
-> IO (NodeMap [Either ErrorMessages ModSummary])
-- The result is the completed NodeMap
loop [] done = return done
- loop ((wanted_mod, is_boot) : ss) done
+ loop (s : ss) done
| Just summs <- Map.lookup key done
= if isSingleton summs then
loop ss done
@@ -2170,7 +2190,12 @@ downsweep hsc_env old_summaries excl_mods allow_dup_roots
loop (calcDeps s) (Map.insert key [Right s] done)
loop ss new_map
where
- key = (unLoc wanted_mod, is_boot)
+ GWIB { gwib_mod = L loc mod, gwib_isBoot = is_boot } = s
+ wanted_mod = L loc mod
+ key = GWIB
+ { gwib_mod = unLoc wanted_mod
+ , gwib_isBoot = is_boot
+ }
-- | Update the every ModSummary that is depended on
-- by a module that needs template haskell. We enable codegen to
@@ -2206,7 +2231,7 @@ enableCodeGenForUnboxedTuplesOrSums =
condition ms =
unboxed_tuples_or_sums (ms_hspp_opts ms) &&
not (gopt Opt_ByteCode (ms_hspp_opts ms)) &&
- not (isBootSummary ms)
+ (isBootSummary ms == NotBoot)
unboxed_tuples_or_sums d =
xopt LangExt.UnboxedTuples d || xopt LangExt.UnboxedSums d
should_modify (ModSummary { ms_hspp_opts = dflags }) =
@@ -2281,10 +2306,11 @@ enableCodeGenWhen condition should_modify staticLife dynLife target nodemap =
-- If a module imports a boot module, msDeps helpfully adds a
-- dependency to that non-boot module in it's result. This
-- means we don't have to think about boot modules here.
- | (L _ mn, NotBoot) <- msDeps ms
- , dep_ms <-
- toList (Map.lookup (mn, NotBoot) nodemap) >>= toList >>=
- toList
+ | dep <- msDeps ms
+ , NotBoot == gwib_isBoot dep
+ , dep_ms_0 <- toList $ Map.lookup (unLoc <$> dep) nodemap
+ , dep_ms_1 <- toList $ dep_ms_0
+ , dep_ms <- toList $ dep_ms_1
]
new_marked_mods = Set.insert ms_mod marked_mods
in foldl' go new_marked_mods deps
@@ -2302,10 +2328,16 @@ mkRootMap summaries = Map.insertListWith (flip (++))
-- modules always contains B.hs if it contains B.hs-boot.
-- Remember, this pass isn't doing the topological sort. It's
-- just gathering the list of all relevant ModSummaries
-msDeps :: ModSummary -> [(Located ModuleName, IsBoot)]
-msDeps s =
- concat [ [(m,IsBoot), (m,NotBoot)] | m <- ms_home_srcimps s ]
- ++ [ (m,NotBoot) | m <- ms_home_imps s ]
+msDeps :: ModSummary -> [GenWithIsBoot (Located ModuleName)]
+msDeps s = [ d
+ | m <- ms_home_srcimps s
+ , d <- [ GWIB { gwib_mod = m, gwib_isBoot = IsBoot }
+ , GWIB { gwib_mod = m, gwib_isBoot = NotBoot }
+ ]
+ ]
+ ++ [ GWIB { gwib_mod = m, gwib_isBoot = NotBoot }
+ | m <- ms_home_imps s
+ ]
-----------------------------------------------------------------------------
-- Summarising modules
@@ -2392,7 +2424,7 @@ findSummaryBySourceFile summaries file
(x:_) -> Just x
checkSummaryTimestamp
- :: HscEnv -> DynFlags -> Bool -> IsBoot
+ :: HscEnv -> DynFlags -> Bool -> IsBootInterface
-> (UTCTime -> IO (Either e ModSummary))
-> ModSummary -> ModLocation -> UTCTime
-> IO (Either e ModSummary)
@@ -2433,7 +2465,7 @@ checkSummaryTimestamp
summariseModule
:: HscEnv
-> NodeMap ModSummary -- Map of old summaries
- -> IsBoot -- IsBoot <=> a {-# SOURCE #-} import
+ -> IsBootInterface -- True <=> a {-# SOURCE #-} import
-> Located ModuleName -- Imported module to be summarised
-> Bool -- object code allowed?
-> Maybe (StringBuffer, UTCTime)
@@ -2445,7 +2477,9 @@ summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod)
| wanted_mod `elem` excl_mods
= return Nothing
- | Just old_summary <- Map.lookup (wanted_mod, is_boot) old_summary_map
+ | Just old_summary <- Map.lookup
+ (GWIB { gwib_mod = wanted_mod, gwib_isBoot = is_boot })
+ old_summary_map
= do -- Find its new timestamp; all the
-- ModSummaries in the old map have valid ml_hs_files
let location = ms_location old_summary
@@ -2491,8 +2525,9 @@ summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod)
just_found location mod = do
-- Adjust location to point to the hs-boot source file,
-- hi file, object file, when is_boot says so
- let location' | IsBoot <- is_boot = addBootSuffixLocn location
- | otherwise = location
+ let location' = case is_boot of
+ IsBoot -> addBootSuffixLocn location
+ NotBoot -> location
src_fn = expectJust "summarise2" (ml_hs_file location')
-- Check that it exists
@@ -2514,10 +2549,10 @@ summariseModule hsc_env old_summary_map is_boot (L loc wanted_mod)
-- case, we know if it's a boot or not because of the {-# SOURCE #-}
-- annotation, but we don't know if it's a signature or a regular
-- module until we actually look it up on the filesystem.
- let hsc_src = case is_boot of
- IsBoot -> HsBootFile
- _ | isHaskellSigFilename src_fn -> HsigFile
- | otherwise -> HsSrcFile
+ let hsc_src
+ | is_boot == IsBoot = HsBootFile
+ | isHaskellSigFilename src_fn = HsigFile
+ | otherwise = HsSrcFile
when (pi_mod_name /= wanted_mod) $
throwE $ unitBag $ mkPlainErrMsg pi_local_dflags pi_mod_name_loc $
@@ -2560,7 +2595,7 @@ data MakeNewModSummary
= MakeNewModSummary
{ nms_src_fn :: FilePath
, nms_src_timestamp :: UTCTime
- , nms_is_boot :: IsBoot
+ , nms_is_boot :: IsBootInterface
, nms_hsc_src :: HscSource
, nms_location :: ModLocation
, nms_mod :: Module
@@ -2604,10 +2639,11 @@ makeNewModSummary hsc_env MakeNewModSummary{..} = do
, ms_obj_date = obj_timestamp
}
-getObjTimestamp :: ModLocation -> IsBoot -> IO (Maybe UTCTime)
+getObjTimestamp :: ModLocation -> IsBootInterface -> IO (Maybe UTCTime)
getObjTimestamp location is_boot
- = if is_boot == IsBoot then return Nothing
- else modificationTimeIfExists (ml_obj_file location)
+ = case is_boot of
+ IsBoot -> return Nothing
+ NotBoot -> modificationTimeIfExists (ml_obj_file location)
data PreprocessedImports
= PreprocessedImports
@@ -2722,8 +2758,11 @@ cyclicModuleErr mss
graph = [ DigraphNode ms (msKey ms) (get_deps ms) | ms <- mss]
get_deps :: ModSummary -> [NodeKey]
- get_deps ms = ([ (unLoc m, IsBoot) | m <- ms_home_srcimps ms ] ++
- [ (unLoc m, NotBoot) | m <- ms_home_imps ms ])
+ get_deps ms =
+ [ GWIB { gwib_mod = unLoc m, gwib_isBoot = IsBoot }
+ | m <- ms_home_srcimps ms ] ++
+ [ GWIB { gwib_mod = unLoc m, gwib_isBoot = NotBoot }
+ | m <- ms_home_imps ms ]
show_path [] = panic "show_path"
show_path [m] = text "module" <+> ppr_ms m
diff --git a/compiler/GHC/Driver/MakeFile.hs b/compiler/GHC/Driver/MakeFile.hs
index f0de5b75c8..6a50ec483f 100644
--- a/compiler/GHC/Driver/MakeFile.hs
+++ b/compiler/GHC/Driver/MakeFile.hs
@@ -247,8 +247,8 @@ processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC node)
| (mb_pkg, L loc mod) <- idecls,
mod `notElem` excl_mods ]
- ; do_imps True (ms_srcimps node)
- ; do_imps False (ms_imps node)
+ ; do_imps IsBoot (ms_srcimps node)
+ ; do_imps NotBoot (ms_imps node)
}
diff --git a/compiler/GHC/Driver/Types.hs b/compiler/GHC/Driver/Types.hs
index c93dc7649f..6903b3608f 100644
--- a/compiler/GHC/Driver/Types.hs
+++ b/compiler/GHC/Driver/Types.hs
@@ -114,7 +114,7 @@ module GHC.Driver.Types (
MonadThings(..),
-- * Information on imports and exports
- WhetherHasOrphans, IsBootInterface, Usage(..),
+ WhetherHasOrphans, IsBootInterface(..), Usage(..),
Dependencies(..), noDependencies,
updNameCache,
IfaceExport,
@@ -745,12 +745,12 @@ hptInstances hsc_env want_this_module
in (concat insts, concat famInsts)
-- | Get rules from modules "below" this one (in the dependency sense)
-hptRules :: HscEnv -> [(ModuleName, IsBootInterface)] -> [CoreRule]
+hptRules :: HscEnv -> [ModuleNameWithIsBoot] -> [CoreRule]
hptRules = hptSomeThingsBelowUs (md_rules . hm_details) False
-- | Get annotations from modules "below" this one (in the dependency sense)
-hptAnns :: HscEnv -> Maybe [(ModuleName, IsBootInterface)] -> [Annotation]
+hptAnns :: HscEnv -> Maybe [ModuleNameWithIsBoot] -> [Annotation]
hptAnns hsc_env (Just deps) = hptSomeThingsBelowUs (md_anns . hm_details) False hsc_env deps
hptAnns hsc_env Nothing = hptAllThings (md_anns . hm_details) hsc_env
@@ -759,7 +759,7 @@ hptAllThings extract hsc_env = concatMap extract (eltsHpt (hsc_HPT hsc_env))
-- | Get things from modules "below" this one (in the dependency sense)
-- C.f Inst.hptInstances
-hptSomeThingsBelowUs :: (HomeModInfo -> [a]) -> Bool -> HscEnv -> [(ModuleName, IsBootInterface)] -> [a]
+hptSomeThingsBelowUs :: (HomeModInfo -> [a]) -> Bool -> HscEnv -> [ModuleNameWithIsBoot] -> [a]
hptSomeThingsBelowUs extract include_hi_boot hsc_env deps
| isOneShot (ghcMode (hsc_dflags hsc_env)) = []
@@ -768,8 +768,8 @@ hptSomeThingsBelowUs extract include_hi_boot hsc_env deps
in
[ thing
| -- Find each non-hi-boot module below me
- (mod, is_boot_mod) <- deps
- , include_hi_boot || not is_boot_mod
+ GWIB { gwib_mod = mod, gwib_isBoot = is_boot } <- deps
+ , include_hi_boot || (is_boot == NotBoot)
-- unsavoury: when compiling the base package with --make, we
-- sometimes try to look up RULES etc for GHC.Prim. GHC.Prim won't
@@ -1114,8 +1114,10 @@ data ModIface_ (phase :: ModIfacePhase)
-- | Old-style accessor for whether or not the ModIface came from an hs-boot
-- file.
-mi_boot :: ModIface -> Bool
-mi_boot iface = mi_hsc_src iface == HsBootFile
+mi_boot :: ModIface -> IsBootInterface
+mi_boot iface = if mi_hsc_src iface == HsBootFile
+ then IsBoot
+ else NotBoot
-- | Lookups up a (possibly cached) fixity from a 'ModIface'. If one cannot be
-- found, 'defaultFixity' is returned instead.
@@ -1141,7 +1143,7 @@ mi_free_holes iface =
-> renameFreeHoles (mkUniqDSet cands) (instUnitInsts (moduleUnit indef))
_ -> emptyUniqDSet
where
- cands = map fst (dep_mods (mi_deps iface))
+ cands = map gwib_mod $ dep_mods $ mi_deps iface
-- | Given a set of free holes, and a unit identifier, rename
-- the free holes according to the instantiation of the unit
@@ -2494,9 +2496,6 @@ type WhetherHasOrphans = Bool
-- | Does this module define family instances?
type WhetherHasFamInst = Bool
--- | Did this module originate from a *-boot file?
-type IsBootInterface = Bool
-
-- | Dependency information about ALL modules and packages below this one
-- in the import hierarchy.
--
@@ -2504,7 +2503,7 @@ type IsBootInterface = Bool
--
-- Invariant: none of the lists contain duplicates.
data Dependencies
- = Deps { dep_mods :: [(ModuleName, IsBootInterface)]
+ = Deps { dep_mods :: [ModuleNameWithIsBoot]
-- ^ All home-package modules transitively below this one
-- I.e. modules that this one imports, or that are in the
-- dep_mods of those directly-imported modules
@@ -2694,7 +2693,7 @@ type PackageCompleteMatchMap = CompleteMatchMap
-- their interface files
data ExternalPackageState
= EPS {
- eps_is_boot :: !(ModuleNameEnv (ModuleName, IsBootInterface)),
+ eps_is_boot :: !(ModuleNameEnv ModuleNameWithIsBoot),
-- ^ In OneShot mode (only), home-package modules
-- accumulate in the external package state, and are
-- sucked in lazily. For these home-pkg modules
@@ -2872,19 +2871,19 @@ isTemplateHaskellOrQQNonBoot :: ModSummary -> Bool
isTemplateHaskellOrQQNonBoot ms =
(xopt LangExt.TemplateHaskell (ms_hspp_opts ms)
|| xopt LangExt.QuasiQuotes (ms_hspp_opts ms)) &&
- not (isBootSummary ms)
+ (isBootSummary ms == NotBoot)
-- | Add a ModSummary to ModuleGraph. Assumes that the new ModSummary is
-- not an element of the ModuleGraph.
extendMG :: ModuleGraph -> ModSummary -> ModuleGraph
extendMG ModuleGraph{..} ms = ModuleGraph
{ mg_mss = ms:mg_mss
- , mg_non_boot = if isBootSummary ms
- then mg_non_boot
- else extendModuleEnv mg_non_boot (ms_mod ms) ms
- , mg_boot = if isBootSummary ms
- then extendModuleSet mg_boot (ms_mod ms)
- else mg_boot
+ , mg_non_boot = case isBootSummary ms of
+ IsBoot -> mg_non_boot
+ NotBoot -> extendModuleEnv mg_non_boot (ms_mod ms) ms
+ , mg_boot = case isBootSummary ms of
+ NotBoot -> mg_boot
+ IsBoot -> extendModuleSet mg_boot (ms_mod ms)
, mg_needs_th_or_qq = mg_needs_th_or_qq || isTemplateHaskellOrQQNonBoot ms
}
@@ -2985,8 +2984,8 @@ msDynObjFilePath :: ModSummary -> DynFlags -> FilePath
msDynObjFilePath ms dflags = dynamicOutputFile dflags (msObjFilePath ms)
-- | Did this 'ModSummary' originate from a hs-boot file?
-isBootSummary :: ModSummary -> Bool
-isBootSummary ms = ms_hsc_src ms == HsBootFile
+isBootSummary :: ModSummary -> IsBootInterface
+isBootSummary ms = if ms_hsc_src ms == HsBootFile then IsBoot else NotBoot
instance Outputable ModSummary where
ppr ms
diff --git a/compiler/GHC/Hs/ImpExp.hs b/compiler/GHC/Hs/ImpExp.hs
index 02eb9db1ca..2257352b63 100644
--- a/compiler/GHC/Hs/ImpExp.hs
+++ b/compiler/GHC/Hs/ImpExp.hs
@@ -18,7 +18,7 @@ module GHC.Hs.ImpExp where
import GHC.Prelude
-import GHC.Unit.Module ( ModuleName )
+import GHC.Unit.Module ( ModuleName, IsBootInterface(..) )
import GHC.Hs.Doc ( HsDocString )
import GHC.Types.Name.Occurrence ( HasOccName(..), isTcOcc, isSymOcc )
import GHC.Types.Basic ( SourceText(..), StringLiteral(..), pprWithSourceText )
@@ -83,7 +83,7 @@ data ImportDecl pass
-- Note [Pragma source text] in GHC.Types.Basic
ideclName :: Located ModuleName, -- ^ Module name.
ideclPkgQual :: Maybe StringLiteral, -- ^ Package qualifier.
- ideclSource :: Bool, -- ^ True <=> {-\# SOURCE \#-} import
+ ideclSource :: IsBootInterface, -- ^ IsBoot <=> {-\# SOURCE \#-} import
ideclSafe :: Bool, -- ^ True => safe import
ideclQualified :: ImportDeclQualifiedStyle, -- ^ If/how the import is qualified.
ideclImplicit :: Bool, -- ^ True => implicit import (of Prelude)
@@ -118,7 +118,7 @@ simpleImportDecl mn = ImportDecl {
ideclSourceSrc = NoSourceText,
ideclName = noLoc mn,
ideclPkgQual = Nothing,
- ideclSource = False,
+ ideclSource = NotBoot,
ideclSafe = False,
ideclImplicit = False,
ideclQualified = NotQualified,
@@ -156,10 +156,10 @@ instance OutputableBndrId p
pp_as Nothing = empty
pp_as (Just a) = text "as" <+> ppr a
- ppr_imp True = case mSrcText of
+ ppr_imp IsBoot = case mSrcText of
NoSourceText -> text "{-# SOURCE #-}"
SourceText src -> text src <+> text "#-}"
- ppr_imp False = empty
+ ppr_imp NotBoot = empty
pp_spec Nothing = empty
pp_spec (Just (False, (L _ ies))) = ppr_ies ies
diff --git a/compiler/GHC/HsToCore/Monad.hs b/compiler/GHC/HsToCore/Monad.hs
index 1914498f4e..02bd5cf91e 100644
--- a/compiler/GHC/HsToCore/Monad.hs
+++ b/compiler/GHC/HsToCore/Monad.hs
@@ -285,7 +285,7 @@ mkDsEnvs dflags mod rdr_env type_env fam_inst_env msg_var cc_st_var
= let if_genv = IfGblEnv { if_doc = text "mkDsEnvs",
if_rec_types = Just (mod, return type_env) }
if_lenv = mkIfLclEnv mod (text "GHC error in desugarer lookup in" <+> ppr mod)
- False -- not boot!
+ NotBoot
real_span = realSrcLocSpan (mkRealSrcLoc (moduleNameFS (moduleName mod)) 1 1)
completeMatchMap = mkCompleteMatchMap complete_matches
gbl_env = DsGblEnv { ds_mod = mod
diff --git a/compiler/GHC/HsToCore/Usage.hs b/compiler/GHC/HsToCore/Usage.hs
index fef8fb03c4..0c48b5744d 100644
--- a/compiler/GHC/HsToCore/Usage.hs
+++ b/compiler/GHC/HsToCore/Usage.hs
@@ -215,9 +215,10 @@ mkPluginUsage hsc_env pluginModule
where
dflags = hsc_dflags hsc_env
platform = targetPlatform dflags
- pNm = moduleName (mi_module pluginModule)
- pPkg = moduleUnit (mi_module pluginModule)
- deps = map fst (dep_mods (mi_deps pluginModule))
+ pNm = moduleName $ mi_module pluginModule
+ pPkg = moduleUnit $ mi_module pluginModule
+ deps = map gwib_mod $
+ dep_mods $ mi_deps pluginModule
-- Lookup object file for a plugin dependency,
-- from the same package as the plugin.
diff --git a/compiler/GHC/Iface/Load.hs b/compiler/GHC/Iface/Load.hs
index 80c4505c8e..ef69e97605 100644
--- a/compiler/GHC/Iface/Load.hs
+++ b/compiler/GHC/Iface/Load.hs
@@ -366,7 +366,7 @@ loadSysInterface doc mod_name = loadInterfaceWithException doc mod_name ImportBy
------------------
-- | Loads a user interface and throws an exception if it fails. The first parameter indicates
-- whether we should import the boot variant of the module
-loadUserInterface :: Bool -> SDoc -> Module -> IfM lcl ModIface
+loadUserInterface :: IsBootInterface -> SDoc -> Module -> IfM lcl ModIface
loadUserInterface is_boot doc mod_name
= loadInterfaceWithException doc mod_name (ImportByUser is_boot)
@@ -485,7 +485,7 @@ loadInterface doc_str mod from
}
}
- ; let bad_boot = mi_boot iface && fmap fst (if_rec_types gbl_env) == Just mod
+ ; let bad_boot = mi_boot iface == IsBoot && fmap fst (if_rec_types gbl_env) == Just mod
-- Warn warn against an EPS-updating import
-- of one's own boot file! (one-shot only)
-- See Note [Loading your own hi-boot file]
@@ -690,7 +690,7 @@ moduleFreeHolesPrecise doc_str mod
Just ifhs -> Just (renameFreeHoles ifhs insts)
_otherwise -> Nothing
readAndCache imod insts = do
- mb_iface <- findAndReadIface (text "moduleFreeHolesPrecise" <+> doc_str) imod mod False
+ mb_iface <- findAndReadIface (text "moduleFreeHolesPrecise" <+> doc_str) imod mod NotBoot
case mb_iface of
Succeeded (iface, _) -> do
let ifhs = mi_free_holes iface
@@ -706,23 +706,25 @@ wantHiBootFile :: DynFlags -> ExternalPackageState -> Module -> WhereFrom
wantHiBootFile dflags eps mod from
= case from of
ImportByUser usr_boot
- | usr_boot && not this_package
+ | usr_boot == IsBoot && not this_package
-> Failed (badSourceImport mod)
| otherwise -> Succeeded usr_boot
ImportByPlugin
- -> Succeeded False
+ -> Succeeded NotBoot
ImportBySystem
| not this_package -- If the module to be imported is not from this package
- -> Succeeded False -- don't look it up in eps_is_boot, because that is keyed
+ -> Succeeded NotBoot -- don't look it up in eps_is_boot, because that is keyed
-- on the ModuleName of *home-package* modules only.
-- We never import boot modules from other packages!
| otherwise
-> case lookupUFM (eps_is_boot eps) (moduleName mod) of
- Just (_, is_boot) -> Succeeded is_boot
- Nothing -> Succeeded False
+ Just (GWIB { gwib_isBoot = is_boot }) ->
+ Succeeded is_boot
+ Nothing ->
+ Succeeded NotBoot
-- The boot-ness of the requested interface,
-- based on the dependencies in directly-imported modules
where
@@ -899,7 +901,7 @@ findAndReadIface :: SDoc
-- sometimes it's ok to fail... see notes with loadInterface
findAndReadIface doc_str mod wanted_mod_with_insts hi_boot_file
= do traceIf (sep [hsep [text "Reading",
- if hi_boot_file
+ if hi_boot_file == IsBoot
then text "[boot]"
else Outputable.empty,
text "interface for",
@@ -1219,11 +1221,11 @@ pprDeps (Deps { dep_mods = mods, dep_pkgs = pkgs, dep_orphs = orphs,
text "family instance modules:" <+> fsep (map ppr finsts)
]
where
- ppr_mod (mod_name, boot) = ppr mod_name <+> ppr_boot boot
+ ppr_mod (GWIB { gwib_mod = mod_name, gwib_isBoot = boot }) = ppr mod_name <+> ppr_boot boot
ppr_pkg (pkg,trust_req) = ppr pkg <>
(if trust_req then text "*" else Outputable.empty)
- ppr_boot True = text "[boot]"
- ppr_boot False = Outputable.empty
+ ppr_boot IsBoot = text "[boot]"
+ ppr_boot NotBoot = Outputable.empty
pprFixities :: [(OccName, Fixity)] -> SDoc
pprFixities [] = Outputable.empty
diff --git a/compiler/GHC/Iface/Recomp.hs b/compiler/GHC/Iface/Recomp.hs
index 68103fc1f4..03223c5712 100644
--- a/compiler/GHC/Iface/Recomp.hs
+++ b/compiler/GHC/Iface/Recomp.hs
@@ -252,7 +252,7 @@ checkVersions hsc_env mod_summary iface
where
this_pkg = thisPackage (hsc_dflags hsc_env)
-- This is a bit of a hack really
- mod_deps :: ModuleNameEnv (ModuleName, IsBootInterface)
+ mod_deps :: ModuleNameEnv ModuleNameWithIsBoot
mod_deps = mkModDeps (dep_mods (mi_deps iface))
-- | Check if any plugins are requesting recompilation
@@ -455,7 +455,7 @@ checkDependencies hsc_env summary iface
case find_res of
Found _ mod
| pkg == this_pkg
- -> if moduleName mod `notElem` map fst prev_dep_mods ++ prev_dep_plgn
+ -> if moduleName mod `notElem` map gwib_mod prev_dep_mods ++ prev_dep_plgn
then do traceHiDiffs $
text "imported module " <> quotes (ppr mod) <>
text " not among previous dependencies"
@@ -474,7 +474,9 @@ checkDependencies hsc_env summary iface
where pkg = moduleUnit mod
_otherwise -> return (RecompBecause reason)
- old_deps = Set.fromList $ map fst $ filter (not . snd) prev_dep_mods
+ 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
@@ -489,7 +491,7 @@ checkDependencies hsc_env summary iface
then return (UpToDate, [])
else do
mb_result <- getFromModIface "need mi_deps for" mod $ \imported_iface -> do
- let mnames = mname:(map fst $ filter (not . snd) $
+ 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)
@@ -1073,7 +1075,7 @@ getOrphanHashes hsc_env mods = do
sortDependencies :: Dependencies -> Dependencies
sortDependencies d
- = Deps { dep_mods = sortBy (compare `on` (moduleNameFS.fst)) (dep_mods d),
+ = Deps { dep_mods = sortBy (compare `on` (moduleNameFS . gwib_mod)) (dep_mods d),
dep_pkgs = sortBy (compare `on` fst) (dep_pkgs d),
dep_orphs = sortBy stableModuleCmp (dep_orphs d),
dep_finsts = sortBy stableModuleCmp (dep_finsts d),
diff --git a/compiler/GHC/IfaceToCore.hs b/compiler/GHC/IfaceToCore.hs
index 48652573f3..b84fe1619d 100644
--- a/compiler/GHC/IfaceToCore.hs
+++ b/compiler/GHC/IfaceToCore.hs
@@ -354,7 +354,7 @@ mergeIfaceDecls = plusOccEnv_C mergeIfaceDecl
typecheckIfacesForMerging :: Module -> [ModIface] -> IORef TypeEnv -> IfM lcl (TypeEnv, [ModDetails])
typecheckIfacesForMerging mod ifaces tc_env_var =
-- cannot be boot (False)
- initIfaceLcl mod (text "typecheckIfacesForMerging") False $ do
+ initIfaceLcl mod (text "typecheckIfacesForMerging") NotBoot $ do
ignore_prags <- goptM Opt_IgnoreInterfacePragmas
-- Build the initial environment
-- NB: Don't include dfuns here, because we don't want to
@@ -506,7 +506,7 @@ tcHiBootIface hsc_src mod
-- it's been compiled once, and we don't need to check the boot iface
then do { hpt <- getHpt
; case lookupHpt hpt (moduleName mod) of
- Just info | mi_boot (hm_iface info)
+ Just info | mi_boot (hm_iface info) == IsBoot
-> mkSelfBootInfo (hm_iface info) (hm_details info)
_ -> return NoSelfBoot }
else do
@@ -517,7 +517,7 @@ tcHiBootIface hsc_src mod
-- that an hi-boot is necessary due to a circular import.
{ read_result <- findAndReadIface
need (fst (getModuleInstantiation mod)) mod
- True -- Hi-boot file
+ IsBoot -- Hi-boot file
; case read_result of {
Succeeded (iface, _path) -> do { tc_iface <- initIfaceTcRn $ typecheckIface iface
@@ -533,14 +533,15 @@ tcHiBootIface hsc_src mod
-- disappeared.
do { eps <- getEps
; case lookupUFM (eps_is_boot eps) (moduleName mod) of
- Nothing -> return NoSelfBoot -- 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) -> failWithTc (elaborate err)
- -- The hi-boot file has mysteriously disappeared.
+ -- The typical case
+ Nothing -> return NoSelfBoot
+ -- error cases
+ Just (GWIB { gwib_isBoot = is_boot }) -> case is_boot of
+ IsBoot -> failWithTc (elaborate err)
+ -- The hi-boot file has mysteriously disappeared.
+ NotBoot -> failWithTc moduleLoop
+ -- Someone below us imported us!
+ -- This is a loop with no hi-boot in the way
}}}}
where
need = text "Need the hi-boot interface for" <+> ppr mod
@@ -1480,8 +1481,9 @@ tcIdInfo ignore_prags toplvl name ty info = do
lcl_env <- getLclEnv
-- Set the CgInfo to something sensible but uninformative before
-- we start; default assumption is that it has CAFs
- let init_info | if_boot lcl_env = vanillaIdInfo `setUnfoldingInfo` BootUnfolding
- | otherwise = vanillaIdInfo
+ let init_info = if if_boot lcl_env == IsBoot
+ then vanillaIdInfo `setUnfoldingInfo` BootUnfolding
+ else vanillaIdInfo
let needed = needed_prags info
foldlM tcPrag init_info needed
diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y
index a9bb4fa87d..50459c673e 100644
--- a/compiler/GHC/Parser.y
+++ b/compiler/GHC/Parser.y
@@ -51,7 +51,7 @@ import qualified Prelude
import GHC.Hs
import GHC.Driver.Phases ( HscSource(..) )
-import GHC.Driver.Types ( IsBootInterface, WarningTxt(..) )
+import GHC.Driver.Types ( IsBootInterface(..), WarningTxt(..) )
import GHC.Driver.Session
import GHC.Driver.Backpack.Syntax
import GHC.Unit.Info
@@ -722,8 +722,8 @@ unitdecl :: { LHsUnitDecl PackageName }
-- XXX not accurate
{ sL1 $2 $ DeclD
(case snd $3 of
- False -> HsSrcFile
- True -> HsBootFile)
+ NotBoot -> HsSrcFile
+ IsBoot -> HsBootFile)
$4
(Just $ sL1 $2 (HsModule (Just $4) $6 (fst $ snd $8) (snd $ snd $8) $5 $1)) }
| maybedocheader 'signature' modid maybemodwarning maybeexports 'where' body
@@ -735,8 +735,8 @@ unitdecl :: { LHsUnitDecl PackageName }
-- will prevent us from parsing both forms.
| maybedocheader 'module' maybe_src modid
{ sL1 $2 $ DeclD (case snd $3 of
- False -> HsSrcFile
- True -> HsBootFile) $4 Nothing }
+ NotBoot -> HsSrcFile
+ IsBoot -> HsBootFile) $4 Nothing }
| maybedocheader 'signature' modid
{ sL1 $2 $ DeclD HsigFile $3 Nothing }
| 'dependency' unitid mayberns
@@ -985,8 +985,8 @@ importdecl :: { LImportDecl GhcPs }
maybe_src :: { (([AddAnn],SourceText),IsBootInterface) }
: '{-# SOURCE' '#-}' { (([mo $1,mc $2],getSOURCE_PRAGs $1)
- , True) }
- | {- empty -} { (([],NoSourceText),False) }
+ , IsBoot) }
+ | {- empty -} { (([],NoSourceText),NotBoot) }
maybe_safe :: { ([AddAnn],Bool) }
: 'safe' { ([mj AnnSafe $1],True) }
diff --git a/compiler/GHC/Parser/Header.hs b/compiler/GHC/Parser/Header.hs
index f6be2a2487..bfdeb71631 100644
--- a/compiler/GHC/Parser/Header.hs
+++ b/compiler/GHC/Parser/Header.hs
@@ -91,7 +91,7 @@ getImports dflags buf filename source_filename = do
main_loc = srcLocSpan (mkSrcLoc (mkFastString source_filename)
1 1)
mod = mb_mod `orElse` L main_loc mAIN_NAME
- (src_idecls, ord_idecls) = partition (ideclSource.unLoc) imps
+ (src_idecls, ord_idecls) = partition ((== IsBoot) . ideclSource . unLoc) imps
-- GHC.Prim doesn't exist physically, so don't go looking for it.
ordinary_imps = filter ((/= moduleName gHC_PRIM) . unLoc
@@ -135,7 +135,7 @@ mkPrelImports this_mod loc implicit_prelude import_decls
ideclSourceSrc = NoSourceText,
ideclName = L loc pRELUDE_NAME,
ideclPkgQual = Nothing,
- ideclSource = False,
+ ideclSource = NotBoot,
ideclSafe = False, -- Not a safe import
ideclQualified = NotQualified,
ideclImplicit = True, -- Implicit!
diff --git a/compiler/GHC/Rename/Env.hs b/compiler/GHC/Rename/Env.hs
index e6fa48c004..89d1e66311 100644
--- a/compiler/GHC/Rename/Env.hs
+++ b/compiler/GHC/Rename/Env.hs
@@ -1347,7 +1347,7 @@ lookupQualifiedNameGHCi rdr_name
, is_ghci
, gopt Opt_ImplicitImportQualified dflags -- Enables this GHCi behaviour
, not (safeDirectImpsReq dflags) -- See Note [Safe Haskell and GHCi]
- = do { res <- loadSrcInterface_maybe doc mod False Nothing
+ = do { res <- loadSrcInterface_maybe doc mod NotBoot Nothing
; case res of
Succeeded iface
-> return [ name
diff --git a/compiler/GHC/Rename/Names.hs b/compiler/GHC/Rename/Names.hs
index 9e7f1a4216..354954f19c 100644
--- a/compiler/GHC/Rename/Names.hs
+++ b/compiler/GHC/Rename/Names.hs
@@ -176,7 +176,7 @@ rnImports imports = do
-- module to import from its implementor
let this_mod = tcg_mod tcg_env
let (source, ordinary) = partition is_source_import imports
- is_source_import d = ideclSource (unLoc d)
+ is_source_import d = ideclSource (unLoc d) == IsBoot
stuff1 <- mapAndReportM (rnImportDecl this_mod) ordinary
stuff2 <- mapAndReportM (rnImportDecl this_mod) source
-- Safe Haskell: See Note [Tracking Trust Transitively]
@@ -323,7 +323,7 @@ rnImportDecl this_mod
-- Compiler sanity check: if the import didn't say
-- {-# SOURCE #-} we should not get a hi-boot file
- WARN( not want_boot && mi_boot iface, ppr imp_mod_name ) do
+ WARN( (want_boot == NotBoot) && (mi_boot iface == IsBoot), ppr imp_mod_name ) do
-- Issue a user warning for a redundant {- SOURCE -} import
-- NB that we arrange to read all the ordinary imports before
@@ -334,7 +334,7 @@ rnImportDecl this_mod
-- the non-boot module depends on the compilation order, which
-- is not deterministic. The hs-boot test can show this up.
dflags <- getDynFlags
- warnIf (want_boot && not (mi_boot iface) && isOneShot (ghcMode dflags))
+ warnIf ((want_boot == IsBoot) && (mi_boot iface == NotBoot) && isOneShot (ghcMode dflags))
(warnRedundantSourceImport imp_mod_name)
when (mod_safe && not (safeImportsOn dflags)) $
addErr (text "safe import can't be used as Safe Haskell isn't on!"
@@ -460,7 +460,10 @@ calculateAvails dflags iface mod_safe' want_boot imported_by =
-- know if any of them depended on CM.hi-boot, in
-- which case we should do the hi-boot consistency
-- check. See GHC.Iface.Load.loadHiBootInterface
- ((moduleName imp_mod,want_boot):dep_mods deps,dep_pkgs deps,ptrust)
+ ( GWIB { gwib_mod = moduleName imp_mod, gwib_isBoot = want_boot } : dep_mods deps
+ , dep_pkgs deps
+ , ptrust
+ )
| otherwise =
-- Imported module is from another package
@@ -1698,20 +1701,23 @@ qualImportItemErr rdr
= hang (text "Illegal qualified name in import item:")
2 (ppr rdr)
+pprImpDeclSpec :: ModIface -> ImpDeclSpec -> SDoc
+pprImpDeclSpec iface decl_spec =
+ quotes (ppr (is_mod decl_spec)) <+> case mi_boot iface of
+ IsBoot -> text "(hi-boot interface)"
+ NotBoot -> Outputable.empty
+
badImportItemErrStd :: ModIface -> ImpDeclSpec -> IE GhcPs -> SDoc
badImportItemErrStd iface decl_spec ie
- = sep [text "Module", quotes (ppr (is_mod decl_spec)), source_import,
+ = sep [text "Module", pprImpDeclSpec iface decl_spec,
text "does not export", quotes (ppr ie)]
- where
- source_import | mi_boot iface = text "(hi-boot interface)"
- | otherwise = Outputable.empty
badImportItemErrDataCon :: OccName -> ModIface -> ImpDeclSpec -> IE GhcPs
-> SDoc
badImportItemErrDataCon dataType_occ iface decl_spec ie
= vcat [ text "In module"
- <+> quotes (ppr (is_mod decl_spec))
- <+> source_import <> colon
+ <+> pprImpDeclSpec iface decl_spec
+ <> colon
, nest 2 $ quotes datacon
<+> text "is a data constructor of"
<+> quotes dataType
@@ -1728,8 +1734,6 @@ badImportItemErrDataCon dataType_occ iface decl_spec ie
datacon_occ = rdrNameOcc $ ieName ie
datacon = parenSymOcc datacon_occ (ppr datacon_occ)
dataType = parenSymOcc dataType_occ (ppr dataType_occ)
- source_import | mi_boot iface = text "(hi-boot interface)"
- | otherwise = Outputable.empty
parens_sp d = parens (space <> d <> space) -- T( f,g )
badImportItemErr :: ModIface -> ImpDeclSpec -> IE GhcPs -> [AvailInfo] -> SDoc
diff --git a/compiler/GHC/Runtime/Linker.hs b/compiler/GHC/Runtime/Linker.hs
index b936bde303..d6b916ff39 100644
--- a/compiler/GHC/Runtime/Linker.hs
+++ b/compiler/GHC/Runtime/Linker.hs
@@ -68,6 +68,7 @@ import Control.Monad
import qualified Data.Set as Set
import Data.Char (isSpace)
+import Data.Function ((&))
import Data.IORef
import Data.List (intercalate, isPrefixOf, isSuffixOf, nub, partition)
import Data.Maybe
@@ -670,21 +671,23 @@ getLinkDeps hsc_env hpt pls replace_osuf span mods
follow_deps (mod:mods) acc_mods acc_pkgs
= do
mb_iface <- initIfaceCheck (text "getLinkDeps") hsc_env $
- loadInterface msg mod (ImportByUser False)
+ loadInterface msg mod (ImportByUser NotBoot)
iface <- case mb_iface of
Maybes.Failed err -> throwGhcExceptionIO (ProgramError (showSDoc dflags err))
Maybes.Succeeded iface -> return iface
- when (mi_boot iface) $ link_boot_mod_error mod
+ when (mi_boot iface == IsBoot) $ link_boot_mod_error mod
let
pkg = moduleUnit mod
deps = mi_deps iface
pkg_deps = dep_pkgs deps
- (boot_deps, mod_deps) = partitionWith is_boot (dep_mods deps)
- where is_boot (m,True) = Left m
- is_boot (m,False) = Right m
+ (boot_deps, mod_deps) = flip partitionWith (dep_mods deps) $
+ \ (GWIB { gwib_mod = m, gwib_isBoot = is_boot }) ->
+ m & case is_boot of
+ IsBoot -> Left
+ NotBoot -> Right
boot_deps' = filter (not . (`elementOfUniqDSet` acc_mods)) boot_deps
acc_mods' = addListToUniqDSet acc_mods (moduleName mod : mod_deps)
diff --git a/compiler/GHC/Tc/Module.hs b/compiler/GHC/Tc/Module.hs
index 94402c0989..267a36cd89 100644
--- a/compiler/GHC/Tc/Module.hs
+++ b/compiler/GHC/Tc/Module.hs
@@ -321,7 +321,7 @@ tcRnImports hsc_env import_decls
= do { (rn_imports, rdr_env, imports, hpc_info) <- rnImports import_decls ;
; this_mod <- getModule
- ; let { dep_mods :: ModuleNameEnv (ModuleName, IsBootInterface)
+ ; let { dep_mods :: ModuleNameEnv ModuleNameWithIsBoot
; dep_mods = imp_dep_mods imports
-- We want instance declarations from all home-package
@@ -1973,7 +1973,7 @@ runTcInteractive hsc_env thing_inside
; let getOrphans m mb_pkg = fmap (\iface -> mi_module iface
: dep_orphs (mi_deps iface))
(loadSrcInterface (text "runTcInteractive") m
- False mb_pkg)
+ NotBoot mb_pkg)
; !orphs <- fmap (force . concat) . forM (ic_imports icxt) $ \i ->
case i of -- force above: see #15111
diff --git a/compiler/GHC/Tc/Types.hs b/compiler/GHC/Tc/Types.hs
index 6e60efd4d5..4da234ea08 100644
--- a/compiler/GHC/Tc/Types.hs
+++ b/compiler/GHC/Tc/Types.hs
@@ -262,7 +262,7 @@ data IfLclEnv
-- Whether or not the IfaceDecl came from a boot
-- file or not; we'll use this to choose between
-- NoUnfolding and BootUnfolding
- if_boot :: Bool,
+ if_boot :: IsBootInterface,
-- The field is used only for error reporting
-- if (say) there's a Lint error in it
@@ -1340,7 +1340,7 @@ data ImportAvails
-- different packages. (currently not the case, but might be in the
-- future).
- imp_dep_mods :: ModuleNameEnv (ModuleName, IsBootInterface),
+ imp_dep_mods :: ModuleNameEnv ModuleNameWithIsBoot,
-- ^ Home-package modules needed by the module being compiled
--
-- It doesn't matter whether any of these dependencies
@@ -1381,15 +1381,15 @@ data ImportAvails
-- including us for imported modules)
}
-mkModDeps :: [(ModuleName, IsBootInterface)]
- -> ModuleNameEnv (ModuleName, IsBootInterface)
+mkModDeps :: [ModuleNameWithIsBoot]
+ -> ModuleNameEnv ModuleNameWithIsBoot
mkModDeps deps = foldl' add emptyUFM deps
- where
- add env elt@(m,_) = addToUFM env m elt
+ where
+ add env elt = addToUFM env (gwib_mod elt) elt
modDepsElts
- :: ModuleNameEnv (ModuleName, IsBootInterface)
- -> [(ModuleName, IsBootInterface)]
+ :: ModuleNameEnv ModuleNameWithIsBoot
+ -> [ModuleNameWithIsBoot]
modDepsElts = sort . nonDetEltsUFM
-- It's OK to use nonDetEltsUFM here because sorting by module names
-- restores determinism
@@ -1426,9 +1426,10 @@ plusImportAvails
imp_orphs = orphs1 `unionLists` orphs2,
imp_finsts = finsts1 `unionLists` finsts2 }
where
- plus_mod_dep r1@(m1, boot1) r2@(m2, boot2)
- | ASSERT2( m1 == m2, (ppr m1 <+> ppr m2) $$ (ppr boot1 <+> ppr boot2) )
- boot1 = r2
+ plus_mod_dep r1@(GWIB { gwib_mod = m1, gwib_isBoot = boot1 })
+ r2@(GWIB {gwib_mod = m2, gwib_isBoot = boot2})
+ | ASSERT2( m1 == m2, (ppr m1 <+> ppr m2) $$ (ppr (boot1 == IsBoot) <+> ppr (boot2 == IsBoot)))
+ boot1 == IsBoot = r2
| otherwise = r1
-- If either side can "see" a non-hi-boot interface, use that
-- Reusing existing tuples saves 10% of allocations on test
@@ -1451,8 +1452,8 @@ data WhereFrom
-- See Note [Care with plugin imports] in GHC.Iface.Load
instance Outputable WhereFrom where
- ppr (ImportByUser is_boot) | is_boot = text "{- SOURCE -}"
- | otherwise = empty
+ ppr (ImportByUser IsBoot) = text "{- SOURCE -}"
+ ppr (ImportByUser NotBoot) = empty
ppr ImportBySystem = text "{- SYSTEM -}"
ppr ImportByPlugin = text "{- PLUGIN -}"
diff --git a/compiler/GHC/Tc/Utils/Backpack.hs b/compiler/GHC/Tc/Utils/Backpack.hs
index d28dad8f70..98458b884b 100644
--- a/compiler/GHC/Tc/Utils/Backpack.hs
+++ b/compiler/GHC/Tc/Utils/Backpack.hs
@@ -549,7 +549,7 @@ mergeSignatures
im = fst (getModuleInstantiation m)
in fmap fst
. withException
- $ findAndReadIface (text "mergeSignatures") im m False
+ $ findAndReadIface (text "mergeSignatures") im m NotBoot
-- STEP 3: Get the unrenamed exports of all these interfaces,
-- thin it according to the export list, and do shaping on them.
@@ -842,7 +842,7 @@ mergeSignatures
-- supposed to include itself in its dep_orphs/dep_finsts. See #13214
iface' = iface { mi_final_exts = (mi_final_exts iface){ mi_orphan = False, mi_finsts = False } }
avails = plusImportAvails (tcg_imports tcg_env) $
- calculateAvails dflags iface' False False ImportedBySystem
+ calculateAvails dflags iface' False NotBoot ImportedBySystem
return tcg_env {
tcg_inst_env = inst_env,
tcg_insts = insts,
@@ -929,7 +929,7 @@ checkImplements impl_mod req_mod@(Module uid mod_name) =
dflags <- getDynFlags
let avails = calculateAvails dflags
- impl_iface False{- safe -} False{- boot -} ImportedBySystem
+ impl_iface False{- safe -} NotBoot ImportedBySystem
fix_env = mkNameEnv [ (gre_name rdr_elt, FixItem occ f)
| (occ, f) <- mi_fixities impl_iface
, rdr_elt <- lookupGlobalRdrEnv impl_gr occ ]
@@ -953,7 +953,7 @@ checkImplements impl_mod req_mod@(Module uid mod_name) =
-- instantiation is correct.
let sig_mod = mkModule (VirtUnit uid) mod_name
isig_mod = fst (getModuleInstantiation sig_mod)
- mb_isig_iface <- findAndReadIface (text "checkImplements 2") isig_mod sig_mod False
+ mb_isig_iface <- findAndReadIface (text "checkImplements 2") isig_mod sig_mod NotBoot
isig_iface <- case mb_isig_iface of
Succeeded (iface, _) -> return iface
Failed err -> failWithTc $
diff --git a/compiler/GHC/Tc/Utils/Monad.hs b/compiler/GHC/Tc/Utils/Monad.hs
index 85b3ad2e96..2fc741ce6f 100644
--- a/compiler/GHC/Tc/Utils/Monad.hs
+++ b/compiler/GHC/Tc/Utils/Monad.hs
@@ -1830,7 +1830,7 @@ setLocalRdrEnv rdr_env thing_inside
************************************************************************
-}
-mkIfLclEnv :: Module -> SDoc -> Bool -> IfLclEnv
+mkIfLclEnv :: Module -> SDoc -> IsBootInterface -> IfLclEnv
mkIfLclEnv mod loc boot
= IfLclEnv { if_mod = mod,
if_loc = loc,
@@ -1887,14 +1887,14 @@ initIfaceCheck doc hsc_env do_this
}
initTcRnIf 'i' hsc_env gbl_env () do_this
-initIfaceLcl :: Module -> SDoc -> Bool -> IfL a -> IfM lcl a
+initIfaceLcl :: Module -> SDoc -> IsBootInterface -> IfL a -> IfM lcl a
initIfaceLcl mod loc_doc hi_boot_file thing_inside
= setLclEnv (mkIfLclEnv mod loc_doc hi_boot_file) thing_inside
-- | Initialize interface typechecking, but with a 'NameShape'
-- to apply when typechecking top-level 'OccName's (see
-- 'lookupIfaceTop')
-initIfaceLclWithSubst :: Module -> SDoc -> Bool -> NameShape -> IfL a -> IfM lcl a
+initIfaceLclWithSubst :: Module -> SDoc -> IsBootInterface -> NameShape -> IfL a -> IfM lcl a
initIfaceLclWithSubst mod loc_doc hi_boot_file nsubst thing_inside
= setLclEnv ((mkIfLclEnv mod loc_doc hi_boot_file) { if_nsubst = Just nsubst }) thing_inside
diff --git a/compiler/GHC/Unit/Module.hs b/compiler/GHC/Unit/Module.hs
index 7eed456311..14751d7003 100644
--- a/compiler/GHC/Unit/Module.hs
+++ b/compiler/GHC/Unit/Module.hs
@@ -9,13 +9,13 @@ These are Uniquable, hence we can build Maps with Modules as
the keys.
-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ExplicitNamespaces #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE ExplicitNamespaces #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TypeSynonymInstances #-}
module GHC.Unit.Module
( module GHC.Unit.Types
@@ -29,7 +29,6 @@ module GHC.Unit.Module
-- * ModuleEnv
, module GHC.Unit.Module.Env
-
-- * Generalization
, getModuleInstantiation
, getUnitInstantiations
@@ -148,4 +147,3 @@ isHoleModule _ = False
-- | Create a hole Module
mkHoleModule :: ModuleName -> GenModule (GenUnit u)
mkHoleModule = Module HoleUnit
-
diff --git a/compiler/GHC/Unit/Module/Location.hs b/compiler/GHC/Unit/Module/Location.hs
index 540f2305d2..7518bd63e8 100644
--- a/compiler/GHC/Unit/Module/Location.hs
+++ b/compiler/GHC/Unit/Module/Location.hs
@@ -9,6 +9,7 @@ module GHC.Unit.Module.Location
where
import GHC.Prelude
+import GHC.Unit.Types
import GHC.Utils.Outputable
-- | Module Location
@@ -54,10 +55,10 @@ addBootSuffix :: FilePath -> FilePath
addBootSuffix path = path ++ "-boot"
-- | Add the @-boot@ suffix if the @Bool@ argument is @True@
-addBootSuffix_maybe :: Bool -> FilePath -> FilePath
-addBootSuffix_maybe is_boot path
- | is_boot = addBootSuffix path
- | otherwise = path
+addBootSuffix_maybe :: IsBootInterface -> FilePath -> FilePath
+addBootSuffix_maybe is_boot path = case is_boot of
+ IsBoot -> addBootSuffix path
+ NotBoot -> path
-- | Add the @-boot@ suffix to all file paths associated with the module
addBootSuffixLocn :: ModLocation -> ModLocation
diff --git a/compiler/GHC/Unit/Types.hs b/compiler/GHC/Unit/Types.hs
index 7282b385b6..04db40a154 100644
--- a/compiler/GHC/Unit/Types.hs
+++ b/compiler/GHC/Unit/Types.hs
@@ -1,7 +1,8 @@
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE NamedFieldPuns #-}
-- | Unit & Module types
--
@@ -63,6 +64,12 @@ module GHC.Unit.Types
, interactiveUnitId
, isInteractiveModule
, wiredInUnitIds
+
+ -- * Boot modules
+ , IsBootInterface (..)
+ , GenWithIsBoot (..)
+ , ModuleNameWithIsBoot
+ , ModuleWithIsBoot
)
where
@@ -634,3 +641,64 @@ wiredInUnitIds =
, thUnitId
, thisGhcUnitId
]
+
+---------------------------------------------------------------------
+-- Boot Modules
+---------------------------------------------------------------------
+
+-- Note [Boot Module Naming]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Why is this section here? After all, these modules are supposed to be about
+-- ways of referring to modules, not modules themselves. Well, the "bootness" of
+-- a module is in a way part of its name, because 'import {-# SOURCE #-} Foo'
+-- references the boot module in particular while 'import Foo' references the
+-- regular module. Backpack signatures live in the normal module namespace (no
+-- special import), so they don't matter here. When dealing with the modules
+-- themselves, however, one should use not 'IsBoot' or conflate signatures and
+-- modules in opposition to boot interfaces. Instead, one should use
+-- 'DriverPhases.HscSource'. See Note [HscSource types].
+
+-- | Indicates whether a module name is referring to a boot interface (hs-boot
+-- file) or regular module (hs file). We need to treat boot modules specially
+-- when building compilation graphs, since they break cycles. Regular source
+-- files and signature files are treated equivalently.
+data IsBootInterface = NotBoot | IsBoot
+ deriving (Eq, Ord, Show, Data)
+
+instance Binary IsBootInterface where
+ put_ bh ib = put_ bh $
+ case ib of
+ NotBoot -> False
+ IsBoot -> True
+ get bh = do
+ b <- get bh
+ return $ case b of
+ False -> NotBoot
+ True -> IsBoot
+
+-- | This data type just pairs a value 'mod' with an IsBootInterface flag. In
+-- practice, 'mod' is usually a @Module@ or @ModuleName@'.
+data GenWithIsBoot mod = GWIB
+ { gwib_mod :: mod
+ , gwib_isBoot :: IsBootInterface
+ } deriving ( Eq, Ord, Show
+ , Functor, Foldable, Traversable
+ )
+
+type ModuleNameWithIsBoot = GenWithIsBoot ModuleName
+
+type ModuleWithIsBoot = GenWithIsBoot Module
+
+instance Binary a => Binary (GenWithIsBoot a) where
+ put_ bh (GWIB { gwib_mod, gwib_isBoot }) = do
+ put_ bh gwib_mod
+ put_ bh gwib_isBoot
+ get bh = do
+ gwib_mod <- get bh
+ gwib_isBoot <- get bh
+ pure $ GWIB { gwib_mod, gwib_isBoot }
+
+instance Outputable a => Outputable (GenWithIsBoot a) where
+ ppr (GWIB { gwib_mod, gwib_isBoot }) = hsep $ ppr gwib_mod : case gwib_isBoot of
+ IsBoot -> []
+ NotBoot -> [text "{-# SOURCE #-}"]