sheaf pushed to branch wip/spj-reinstallable-base2 at Glasgow Haskell Compiler / GHC
Commits:
-
1575eb10
by sheaf at 2026-07-28T00:18:35+02:00
16 changed files:
- compiler/GHC/Builtin.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/Iface/Errors/Ppr.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Unit/External.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/State.hs
- libraries/base/base.cabal.in
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- utils/dump-decls/Main.hs
Changes:
| ... | ... | @@ -225,8 +225,7 @@ How known-occ entities work |
| 225 | 225 | This is a big reason for (KnownOccNameInvariant): an export list cannot have two
|
| 226 | 226 | entities with the same OccName.
|
| 227 | 227 | |
| 228 | - When GHC wants to find GHC.Essentials, it just looks for it in the same
|
|
| 229 | - way as any other import.
|
|
| 228 | + See Note [Finding GHC.Essentials] for how GHC finds the GHC.Essentials module.
|
|
| 230 | 229 | |
| 231 | 230 | * There are three flags that control the treatment of known entities:
|
| 232 | 231 | -frebindable-known-names
|
| ... | ... | @@ -412,10 +411,9 @@ To make `wombat` into a known-key name, do the following. |
| 412 | 411 | * Just like for known-occ names above, in any module in `base` or `ghc-internal` (which
|
| 413 | 412 | are compiled with -frebindable-known-names), ensure that `wombat` is
|
| 414 | 413 | in scope by saying `import M( wombat )`.
|
| 415 | --}
|
|
| 416 | 414 | |
| 417 | -{- Note [Known entities and reinstallable base]
|
|
| 418 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 415 | +Note [Known entities and reinstallable base]
|
|
| 416 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 419 | 417 | The design of known-entities in GHC, described in Note [Overview of known entities],
|
| 420 | 418 | is carefully crafted to support a single version of GHC to compile different
|
| 421 | 419 | versions of base, even though GHC itself is compiled against a fixed version of
|
| ... | ... | @@ -453,6 +451,45 @@ Let's compare two examples: `coerce` and `enumFromTo`. |
| 453 | 451 | `enumFromTo` (see `GHC.Iface.Load.lookupKnownOccName`). This means GHC never
|
| 454 | 452 | needs to know where precisely `enumFromTo` is defined, allowing it to be
|
| 455 | 453 | defined anywhere (wherever in `base`, or in a module imported by `base`).
|
| 454 | + |
|
| 455 | +Note [Finding GHC.Essentials]
|
|
| 456 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 457 | +As explained in Note [Overview of known entities], when compiling a module that
|
|
| 458 | +does not enable -frebindable-known-names, GHC resolves known entities by looking
|
|
| 459 | +them up in GHC.Essentials. Every module that does not enable
|
|
| 460 | +-frebindable-known-names therefore acquires an implicit dependency on GHC.Essentials.
|
|
| 461 | + |
|
| 462 | +As GHC.Essentials is an implementation detail, we would really rather not insist
|
|
| 463 | +that it be an exposed module (e.g. of 'base'). So we must ensure that GHC can
|
|
| 464 | +still adequately resolve the implicit dependency even if GHC.Essentials is hidden.
|
|
| 465 | + |
|
| 466 | +Hidden-ness only ever obstructs the resolution of a 'ModuleName' into a 'Module'.
|
|
| 467 | +Thus, to allow GHC.Essentials to be hidden (not available via user-written
|
|
| 468 | +imports) while retaining the ability to resolve known entities, we follow the
|
|
| 469 | +following plan:
|
|
| 470 | + |
|
| 471 | + (FindEssentials1)
|
|
| 472 | + 'GHC.Unit.Finder.findModuleWithIsBoot' has special logic to resolve a
|
|
| 473 | + possibly hidden GHC.Essentials module, using 'GHC.Unit.Finder.findEssentialsModule'.
|
|
| 474 | + |
|
| 475 | + Every code path that needs to find GHC.Essentials despite it being hidden
|
|
| 476 | + goes through here, including:
|
|
| 477 | + |
|
| 478 | + - downsweep GHC.Driver.Downsweep.summariseModuleDispatch
|
|
| 479 | + - ghc -M GHC.Driver.MakeFile.findDependency
|
|
| 480 | + - recompilation checking GHC.Iface.Recomp.checkDependencies
|
|
| 481 | + |
|
| 482 | + Source-written imports go via 'GHC.Iface.Load.loadSrcInterface_maybe',
|
|
| 483 | + which uses 'GHC.Unit.Finder.findImportedModule', which rejects hidden modules.
|
|
| 484 | + |
|
| 485 | + (FindEssentials2)
|
|
| 486 | + 'GHC.Unit.Module.Deps.mkDependencies' records the unit that provides
|
|
| 487 | + GHC.Essentials, so that the implicit dependency appears in the interface file.
|
|
| 488 | + |
|
| 489 | + (FindEssentials3)
|
|
| 490 | + 'GHC.Driver.Make.warnUnusedPackages' has a special case to ensure that we
|
|
| 491 | + don't flag up the unit that provides GHC.Essentials as unused when it is
|
|
| 492 | + only implicitly imported.
|
|
| 456 | 493 | -}
|
| 457 | 494 | |
| 458 | 495 | {-
|
| ... | ... | @@ -1374,9 +1374,8 @@ summariseModuleDispatch k hsc_env' home_unit is_boot (L _ wanted_mod) mb_pkg exc |
| 1374 | 1374 | hsc_env = hscSetActiveHomeUnit home_unit hsc_env'
|
| 1375 | 1375 | |
| 1376 | 1376 | find_it :: IO SummariseResult
|
| 1377 | - |
|
| 1378 | 1377 | find_it = do
|
| 1379 | - found <- findImportedModuleWithIsBoot hsc_env wanted_mod is_boot mb_pkg
|
|
| 1378 | + found <- findModuleWithIsBoot hsc_env wanted_mod is_boot mb_pkg
|
|
| 1380 | 1379 | case found of
|
| 1381 | 1380 | Found location mod
|
| 1382 | 1381 | | moduleUnitId mod `Set.member` hsc_all_home_unit_ids hsc_env ->
|
| ... | ... | @@ -305,8 +305,8 @@ findDependency :: HscEnv |
| 305 | 305 | -> IO (Either (MsgEnvelope GhcMessage) (Maybe FilePath)) -- Interface file
|
| 306 | 306 | findDependency hsc_env srcloc pkg imp is_boot include_pkg_deps = do
|
| 307 | 307 | -- Find the module; this will be fast because
|
| 308 | - -- we've done it once during downsweep
|
|
| 309 | - r <- findImportedModuleWithIsBoot hsc_env imp is_boot pkg
|
|
| 308 | + -- we've done it once during downsweep.
|
|
| 309 | + r <- findModuleWithIsBoot hsc_env imp is_boot pkg
|
|
| 310 | 310 | case r of
|
| 311 | 311 | Found loc _
|
| 312 | 312 | -- Home package: just depend on the .hi or hi-boot file
|
| ... | ... | @@ -106,7 +106,7 @@ import GHC.Unit.Module.Deps |
| 106 | 106 | import Data.List (partition)
|
| 107 | 107 | import Data.IORef
|
| 108 | 108 | import GHC.Types.Unique.FM
|
| 109 | -import GHC.Iface.Load (KnownEntitySource(..), lookupKnownKeyName, lookupKnownKeysModule)
|
|
| 109 | +import GHC.Iface.Load (KnownEntitySource(..), lookupKnownKeyName, essentialsUnitId)
|
|
| 110 | 110 | import GHC.HsToCore.Types (DsGblEnv(..))
|
| 111 | 111 | |
| 112 | 112 | {-
|
| ... | ... | @@ -228,12 +228,12 @@ deSugar hsc_env |
| 228 | 228 | |
| 229 | 229 | ; let pluginModules = map lpModule (loadedPlugins (hsc_plugins hsc_env))
|
| 230 | 230 | home_unit = hsc_home_unit hsc_env
|
| 231 | - ; essentials_mod <- liftIO $ lookupKnownKeysModule hsc_env dflags
|
|
| 231 | + ; essentials_uid <- liftIO $ essentialsUnitId hsc_env dflags
|
|
| 232 | 232 | ; let deps = mkDependencies home_unit
|
| 233 | 233 | (tcg_mod tcg_env)
|
| 234 | 234 | (tcg_imports tcg_env)
|
| 235 | 235 | (map mi_module pluginModules)
|
| 236 | - (moduleUnitId <$> essentials_mod)
|
|
| 236 | + essentials_uid
|
|
| 237 | 237 | |
| 238 | 238 | ; safe_mode <- finalSafeMode dflags tcg_env
|
| 239 | 239 |
| ... | ... | @@ -210,7 +210,7 @@ cantFindErrorX pkg_hidden_hint may_show_locations mod_or_interface (CantFindInst |
| 210 | 210 | -- package flags when making suggestions. ToDo: if the original package
|
| 211 | 211 | -- also has a reexport, prefer that one
|
| 212 | 212 | pp_sugg (SuggestVisible m mod o) = ppr m <+> provenance o
|
| 213 | - where provenance ModHidden = empty
|
|
| 213 | + where provenance (ModHidden {}) = empty
|
|
| 214 | 214 | provenance (ModUnusable _) = empty
|
| 215 | 215 | provenance (ModOrigin{ fromOrigUnit = e,
|
| 216 | 216 | fromExposedReexport = res,
|
| ... | ... | @@ -227,7 +227,7 @@ cantFindErrorX pkg_hidden_hint may_show_locations mod_or_interface (CantFindInst |
| 227 | 227 | <+> ppr mod)
|
| 228 | 228 | | otherwise = empty
|
| 229 | 229 | pp_sugg (SuggestHidden m mod o) = ppr m <+> provenance o
|
| 230 | - where provenance ModHidden = empty
|
|
| 230 | + where provenance (ModHidden {}) = empty
|
|
| 231 | 231 | provenance (ModUnusable _) = empty
|
| 232 | 232 | provenance (ModOrigin{ fromOrigUnit = e,
|
| 233 | 233 | fromHiddenReexport = rhs })
|
| ... | ... | @@ -261,7 +261,7 @@ cantFindErrorX pkg_hidden_hint may_show_locations mod_or_interface (CantFindInst |
| 261 | 261 | where
|
| 262 | 262 | pprMod (m, o) = text "it is bound as" <+> ppr m <+>
|
| 263 | 263 | text "by" <+> pprOrigin m o
|
| 264 | - pprOrigin _ ModHidden = panic "cantFindErr: bound by mod hidden"
|
|
| 264 | + pprOrigin _ (ModHidden {}) = panic "cantFindErr: bound by mod hidden"
|
|
| 265 | 265 | pprOrigin _ (ModUnusable _) = panic "cantFindErr: bound by mod unusable"
|
| 266 | 266 | pprOrigin m (ModOrigin e res _ f) = sep $ punctuate comma (
|
| 267 | 267 | if e == Just True
|
| ... | ... | @@ -24,7 +24,7 @@ module GHC.Iface.Load ( |
| 24 | 24 | lookupKnownKeyThing, lookupKnownKeyName,
|
| 25 | 25 | lookupKnownOccThing, lookupKnownOccName,
|
| 26 | 26 | loadKnownKeyOccMaps, lookupKnownGRE,
|
| 27 | - lookupKnownKeysMap, lookupKnownKeysModule,
|
|
| 27 | + lookupKnownKeysMap, essentialsUnitId,
|
|
| 28 | 28 | |
| 29 | 29 | -- RnM/TcM functions
|
| 30 | 30 | loadModuleInterface, loadModuleInterfaces,
|
| ... | ... | @@ -302,13 +302,14 @@ loadKnownKeyOccMaps |
| 302 | 302 | -- We don't have a KnownKeyOccMap yet, so create it
|
| 303 | 303 | -- from the interface file for KnownKeyName
|
| 304 | 304 | do { hsc_env <- getTopEnv
|
| 305 | - ; mb_res <- liftIO $ findImportedModule hsc_env eSSENTIALS_NAME NoPkgQual
|
|
| 306 | - ; case mb_res of
|
|
| 307 | - Found _ mod -> Succeeded <$> build_maps mod
|
|
| 308 | - fr -> return (Failed (CantFindEssentials
|
|
| 309 | - (cannotFindModule hsc_env eSSENTIALS_NAME fr)
|
|
| 310 | - UnknownLoadEssentialsReason))
|
|
| 311 | - } } }
|
|
| 305 | + ; res <- liftIO $ getEssentialsModule hsc_env
|
|
| 306 | + ; case res of
|
|
| 307 | + Succeeded mod -> Succeeded <$> build_maps mod
|
|
| 308 | + Failed err ->
|
|
| 309 | + return $ Failed $
|
|
| 310 | + CantFindEssentials err UnknownLoadEssentialsReason
|
|
| 311 | + }}}
|
|
| 312 | + |
|
| 312 | 313 | where
|
| 313 | 314 | doc = text "Need interface for KnownKeyNames"
|
| 314 | 315 | |
| ... | ... | @@ -372,23 +373,39 @@ checkKnownKeyNamesIface known_key_names_occ_map |
| 372 | 373 | Just name -> getOccName name /= occ
|
| 373 | 374 | #endif
|
| 374 | 375 | |
| 375 | --- | Lookup the module exporting the canonical known-entities definitions (GHC.Essentials)
|
|
| 376 | -lookupKnownKeysModule :: HscEnv -> DynFlags {-^ Module dyn flags -} -> IO (Maybe Module)
|
|
| 377 | -lookupKnownKeysModule hsc_env dflags = do
|
|
| 378 | - eps <- hscEPS hsc_env
|
|
| 379 | - case eps_known_keys eps of
|
|
| 380 | - Just (_, kk_mod) -> return (Just kk_mod)
|
|
| 381 | - Nothing -> do
|
|
| 382 | - found_essentials <- findImportedModule hsc_env eSSENTIALS_NAME NoPkgQual
|
|
| 383 | - let rebindable_kn = gopt Opt_RebindableKnownNames dflags
|
|
| 384 | - let essentials_uid
|
|
| 385 | - | rebindable_kn = return Nothing
|
|
| 386 | - | Found _ mod <- found_essentials = return (Just mod)
|
|
| 387 | - | fr <- found_essentials = do
|
|
| 388 | - throwOneError (initSourceErrorContext dflags) $
|
|
| 389 | - mkPlainErrorMsgEnvelope noSrcSpan $ GhcDriverMessage $ DriverInterfaceError $
|
|
| 390 | - CantFindEssentials (cannotFindModule hsc_env eSSENTIALS_NAME fr) LookingForEssentialsModule
|
|
| 391 | - essentials_uid
|
|
| 376 | +-- | Identify the 'GHC.Essentials' module to use.
|
|
| 377 | +getEssentialsModule :: HscEnv -> IO (MaybeErr MissingInterfaceError Module)
|
|
| 378 | +getEssentialsModule hsc_env
|
|
| 379 | + = do { fr <- findEssentialsModule hsc_env
|
|
| 380 | + ; return $ case fr of
|
|
| 381 | + Found _ mod -> Succeeded mod
|
|
| 382 | + _ -> Failed $ cannotFindModule hsc_env eSSENTIALS_NAME fr }
|
|
| 383 | + |
|
| 384 | +-- | Find the unit that provides the 'GHC.Essentials' module that is
|
|
| 385 | +-- implicitly depended on.
|
|
| 386 | +--
|
|
| 387 | +-- 'Nothing' when @-frebindable-known-names@ is on, as in that case there is
|
|
| 388 | +-- no implicit dependency.
|
|
| 389 | +--
|
|
| 390 | +-- See Note [Finding GHC.Essentials] in GHC.Builtin.
|
|
| 391 | +essentialsUnitId :: HscEnv -> DynFlags {-^ Module dyn flags -} -> IO (Maybe UnitId)
|
|
| 392 | +essentialsUnitId hsc_env dflags
|
|
| 393 | + | gopt Opt_RebindableKnownNames dflags
|
|
| 394 | + = return Nothing
|
|
| 395 | + | otherwise
|
|
| 396 | + = do { eps <- hscEPS hsc_env
|
|
| 397 | + ; case eps_known_keys eps of
|
|
| 398 | + -- We already resolved it: re-use the cached value.
|
|
| 399 | + Just (_, kk_mod) -> return (Just (moduleUnitId kk_mod))
|
|
| 400 | + Nothing ->
|
|
| 401 | + do { res <- getEssentialsModule hsc_env
|
|
| 402 | + ; case res of
|
|
| 403 | + Succeeded mod -> return (Just (moduleUnitId mod))
|
|
| 404 | + Failed err ->
|
|
| 405 | + throwOneError (initSourceErrorContext dflags) $
|
|
| 406 | + mkPlainErrorMsgEnvelope noSrcSpan $
|
|
| 407 | + GhcDriverMessage $ DriverInterfaceError $
|
|
| 408 | + CantFindEssentials err LookingForEssentialsModule } }
|
|
| 392 | 409 | |
| 393 | 410 | {- *********************************************************************
|
| 394 | 411 | * *
|
| ... | ... | @@ -244,12 +244,12 @@ mkIfaceTc hsc_env safe_mode mod_details mod_summary mb_program mb_modBreaks |
| 244 | 244 | = do let pluginModules = map lpModule (loadedPlugins (hsc_plugins hsc_env))
|
| 245 | 245 | let home_unit = hsc_home_unit hsc_env
|
| 246 | 246 | let dflags = ms_hspp_opts mod_summary
|
| 247 | - essentials_mod <- liftIO $ lookupKnownKeysModule hsc_env dflags
|
|
| 247 | + essentials_uid <- liftIO $ essentialsUnitId hsc_env dflags
|
|
| 248 | 248 | let deps = mkDependencies home_unit
|
| 249 | 249 | (tcg_mod tc_result)
|
| 250 | 250 | (tcg_imports tc_result)
|
| 251 | 251 | (map mi_module pluginModules)
|
| 252 | - (moduleUnitId <$> essentials_mod)
|
|
| 252 | + essentials_uid
|
|
| 253 | 253 | |
| 254 | 254 | usage <- mkRecompUsageInfo hsc_env tc_result
|
| 255 | 255 | docs <- extractDocs dflags tc_result
|
| ... | ... | @@ -638,7 +638,8 @@ checkMergedSignatures hsc_env mod_summary self_recomp = do |
| 638 | 638 | checkDependencies :: HscEnv -> ModSummary -> ModIface -> IfG RecompileRequired
|
| 639 | 639 | checkDependencies hsc_env summary iface
|
| 640 | 640 | = do
|
| 641 | - res_normal <- classify_import (findImportedModule hsc_env)
|
|
| 641 | + -- See (FindEssentials2) in Note [Finding GHC.Essentials] in GHC.Builtin.
|
|
| 642 | + res_normal <- classify_import (\mod pkg -> findModuleWithIsBoot hsc_env mod NotBoot pkg)
|
|
| 642 | 643 | ([(st, p, m) | (st, p, m) <- (ms_textual_imps summary)]
|
| 643 | 644 | ++
|
| 644 | 645 | [(NormalLevel, NoPkgQual, m) | m <- ms_srcimps summary ])
|
| ... | ... | @@ -156,6 +156,12 @@ data ExternalPackageState |
| 156 | 156 | eps_known_keys :: Maybe (KnownKeyNameMaps, Module),
|
| 157 | 157 | -- ^ See Note [Overview of known entities].
|
| 158 | 158 | -- Caches the 'Module' where known entities are defined.
|
| 159 | + --
|
|
| 160 | + -- BEWARE: there is a single 'ExternalPackageState' for
|
|
| 161 | + -- the whole session, so this caches a single 'GHC.Essentials'
|
|
| 162 | + -- for all home units. If two home units are compiled
|
|
| 163 | + -- against two different units both providing GHC.Essentials,
|
|
| 164 | + -- whichever is resolved first will be used for both.
|
|
| 159 | 165 | |
| 160 | 166 | eps_inst_env :: !PackageInstEnv, -- ^ The total 'InstEnv' accumulated
|
| 161 | 167 | -- from all the external-package modules
|
| ... | ... | @@ -14,7 +14,8 @@ module GHC.Unit.Finder ( |
| 14 | 14 | FinderCache(..),
|
| 15 | 15 | initFinderCache,
|
| 16 | 16 | findImportedModule,
|
| 17 | - findImportedModuleWithIsBoot,
|
|
| 17 | + findModuleWithIsBoot,
|
|
| 18 | + findEssentialsModule,
|
|
| 18 | 19 | findPluginModule,
|
| 19 | 20 | findExactModule,
|
| 20 | 21 | findHomeModule,
|
| ... | ... | @@ -43,6 +44,7 @@ import GHC.Data.OsPath |
| 43 | 44 | |
| 44 | 45 | import GHC.Unit.Env
|
| 45 | 46 | import GHC.Unit.Types
|
| 47 | +import GHC.Builtin.Modules( eSSENTIALS_NAME )
|
|
| 46 | 48 | import GHC.Unit.Module
|
| 47 | 49 | import GHC.Unit.Module.Graph
|
| 48 | 50 | (
|
| ... | ... | @@ -191,11 +193,45 @@ findImportedModule hsc_env mod pkg_qual = |
| 191 | 193 | let home_module_name_providers_map = mgHomeModuleNameProvidersMap (hsc_mod_graph hsc_env)
|
| 192 | 194 | findImportedModuleNoHsc fc fopts (hsc_unit_env hsc_env) home_module_name_providers_map mb_home_unit mod pkg_qual
|
| 193 | 195 | |
| 194 | -findImportedModuleWithIsBoot :: HscEnv -> ModuleName -> IsBootInterface -> PkgQual -> IO FindResult
|
|
| 195 | -findImportedModuleWithIsBoot hsc_env mod is_boot pkg_qual = do
|
|
| 196 | - res <- findImportedModule hsc_env mod pkg_qual
|
|
| 197 | - case (res, is_boot) of
|
|
| 198 | - (Found loc mod, IsBoot) -> return (Found (addBootSuffixLocn loc) mod)
|
|
| 196 | +-- | Resolve a 'ModuleName' into a 'Module'.
|
|
| 197 | +--
|
|
| 198 | +-- Use this wherever GHC resolves a module's dependencies.
|
|
| 199 | +--
|
|
| 200 | +-- Resolving a user-written import must use 'findImportedModule' instead.
|
|
| 201 | +findModuleWithIsBoot :: HscEnv -> ModuleName -> IsBootInterface -> PkgQual -> IO FindResult
|
|
| 202 | +findModuleWithIsBoot hsc_env mod_name is_boot pkg_qual
|
|
| 203 | + -- Allow GHC.Essentials to be found even when it is hidden.
|
|
| 204 | + -- See (FindEssentials1) in Note [Finding GHC.Essentials] in GHC.Builtin.
|
|
| 205 | + | mod_name == eSSENTIALS_NAME
|
|
| 206 | + , NotBoot <- is_boot
|
|
| 207 | + = findEssentialsModule hsc_env
|
|
| 208 | + | otherwise
|
|
| 209 | + = do res <- findImportedModule hsc_env mod_name pkg_qual
|
|
| 210 | + case (res, is_boot) of
|
|
| 211 | + (Found loc mod, IsBoot) -> return (Found (addBootSuffixLocn loc) mod)
|
|
| 212 | + _ -> return res
|
|
| 213 | + |
|
| 214 | +-- | Find 'GHC.Essentials' (allowing it to be a hidden module of its unit).
|
|
| 215 | +--
|
|
| 216 | +-- See Note [Finding GHC.Essentials] in GHC.Builtin.
|
|
| 217 | +findEssentialsModule :: HscEnv -> IO FindResult
|
|
| 218 | +findEssentialsModule hsc_env = do
|
|
| 219 | + res <- findImportedModule hsc_env eSSENTIALS_NAME NoPkgQual
|
|
| 220 | + case res of
|
|
| 221 | + NotFound {}
|
|
| 222 | + | Just mod <- lookupModuleEvenIfHidden (hsc_units hsc_env) eSSENTIALS_NAME
|
|
| 223 | + -> do let im = fst (getModuleInstantiation mod)
|
|
| 224 | + r <- findExactModule hsc_env im NotBoot
|
|
| 225 | + return $ case r of
|
|
| 226 | + InstalledFound loc -> Found loc mod
|
|
| 227 | + InstalledNoPackage _ -> NoPackage (moduleUnit mod)
|
|
| 228 | + InstalledNotFound fps _ ->
|
|
| 229 | + NotFound { fr_paths = fmap unsafeDecodeUtf fps
|
|
| 230 | + , fr_pkg = Just (moduleUnit mod)
|
|
| 231 | + , fr_pkgs_hidden = []
|
|
| 232 | + , fr_mods_hidden = []
|
|
| 233 | + , fr_unusables = []
|
|
| 234 | + , fr_suggestions = [] }
|
|
| 199 | 235 | _ -> return res
|
| 200 | 236 | |
| 201 | 237 | findImportedModuleNoHsc
|
| ... | ... | @@ -32,12 +32,14 @@ module GHC.Unit.State ( |
| 32 | 32 | listVisibleModuleNames,
|
| 33 | 33 | lookupModuleInAllUnits,
|
| 34 | 34 | lookupModuleWithSuggestions,
|
| 35 | + lookupModuleEvenIfHidden,
|
|
| 35 | 36 | lookupModulePackage,
|
| 36 | 37 | lookupPluginModuleWithSuggestions,
|
| 37 | 38 | requirementMerges,
|
| 38 | 39 | LookupResult(..),
|
| 39 | 40 | ModuleSuggestion(..),
|
| 40 | 41 | ModuleOrigin(..),
|
| 42 | + HiddenModuleUnit(..),
|
|
| 41 | 43 | UnusableUnit(..),
|
| 42 | 44 | UnusableUnitReason(..),
|
| 43 | 45 | pprReason,
|
| ... | ... | @@ -81,6 +83,7 @@ import GHC.Platform.Ways |
| 81 | 83 | import GHC.Unit.Database
|
| 82 | 84 | import GHC.Unit.Info
|
| 83 | 85 | import GHC.Unit.Ppr
|
| 86 | +import GHC.Builtin.Modules( eSSENTIALS_NAME )
|
|
| 84 | 87 | import GHC.Unit.Types
|
| 85 | 88 | import GHC.Unit.Module
|
| 86 | 89 | import GHC.Unit.Home
|
| ... | ... | @@ -168,10 +171,8 @@ import Control.Applicative |
| 168 | 171 | -- it could have come into scope. Warning: don't use the record functions,
|
| 169 | 172 | -- they're partial!
|
| 170 | 173 | data ModuleOrigin =
|
| 171 | - -- | Module is hidden, and thus never will be available for import.
|
|
| 172 | - -- (But maybe the user didn't realize), so we'll still keep track
|
|
| 173 | - -- of these modules.)
|
|
| 174 | - ModHidden
|
|
| 174 | + -- | The module is hidden (thus not available for a user-written import).
|
|
| 175 | + ModHidden !HiddenModuleUnit
|
|
| 175 | 176 | |
| 176 | 177 | -- | Module is unavailable because the unit is unusable.
|
| 177 | 178 | | ModUnusable !UnusableUnit
|
| ... | ... | @@ -193,6 +194,11 @@ data ModuleOrigin = |
| 193 | 194 | , fromPackageFlag :: Bool
|
| 194 | 195 | }
|
| 195 | 196 | |
| 197 | +-- | Is the unit providing a hidden module itself visible in this compilation?
|
|
| 198 | +data HiddenModuleUnit
|
|
| 199 | + = HiddenModInVisibleUnit
|
|
| 200 | + | HiddenModInHiddenUnit
|
|
| 201 | + |
|
| 196 | 202 | -- | A unusable unit module origin
|
| 197 | 203 | data UnusableUnit = UnusableUnit
|
| 198 | 204 | { uuUnit :: !Unit -- ^ Unusable unit
|
| ... | ... | @@ -201,7 +207,7 @@ data UnusableUnit = UnusableUnit |
| 201 | 207 | }
|
| 202 | 208 | |
| 203 | 209 | instance Outputable ModuleOrigin where
|
| 204 | - ppr ModHidden = text "hidden module"
|
|
| 210 | + ppr (ModHidden {}) = text "hidden module"
|
|
| 205 | 211 | ppr (ModUnusable _) = text "unusable module"
|
| 206 | 212 | ppr (ModOrigin e res rhs f) = sep (punctuate comma (
|
| 207 | 213 | (case e of
|
| ... | ... | @@ -255,7 +261,7 @@ instance Monoid ModuleOrigin where |
| 255 | 261 | -- | Is the name from the import actually visible? (i.e. does it cause
|
| 256 | 262 | -- ambiguity, or is it only relevant when we're making suggestions?)
|
| 257 | 263 | originVisible :: ModuleOrigin -> Bool
|
| 258 | -originVisible ModHidden = False
|
|
| 264 | +originVisible (ModHidden {}) = False
|
|
| 259 | 265 | originVisible (ModUnusable _) = False
|
| 260 | 266 | originVisible (ModOrigin b res _ f) = b == Just True || not (null res) || f
|
| 261 | 267 | |
| ... | ... | @@ -1819,7 +1825,11 @@ mkModuleNameProvidersMap logger cfg pkg_map vis_map = |
| 1819 | 1825 | esmap = listToUFM (es False) -- parameter here doesn't matter, orig will
|
| 1820 | 1826 | -- be overwritten
|
| 1821 | 1827 | |
| 1822 | - hiddens = [(m, mkModMap pk m ModHidden) | m <- hidden_mods]
|
|
| 1828 | + hiddens = [(m, mkModMap pk m (ModHidden hidden_mod_unit)) | m <- hidden_mods]
|
|
| 1829 | + |
|
| 1830 | + hidden_mod_unit
|
|
| 1831 | + | b || not (null rns) = HiddenModInVisibleUnit
|
|
| 1832 | + | otherwise = HiddenModInHiddenUnit
|
|
| 1823 | 1833 | |
| 1824 | 1834 | pk = mkUnit pkg
|
| 1825 | 1835 | unit_lookup uid = lookupUnit' (unitConfigAllowVirtual cfg) pkg_map uid
|
| ... | ... | @@ -1940,8 +1950,36 @@ lookupModulePackage pkgs mn mfs = |
| 1940 | 1950 | |
| 1941 | 1951 | _ -> Nothing
|
| 1942 | 1952 | |
| 1953 | + -- If we implicitly depend on GHC.Essentials, mark the unit providing it
|
|
| 1954 | + -- as used. See (FindEssentials4) in Note [Finding GHC.Essentials] in GHC.Builtin.
|
|
| 1955 | + LookupHidden {}
|
|
| 1956 | + | mn == eSSENTIALS_NAME
|
|
| 1957 | + -> (\m -> [m]) <$> (lookupUnit pkgs . moduleUnit =<< lookupModuleEvenIfHidden pkgs mn)
|
|
| 1958 | + |
|
| 1943 | 1959 | _ -> Nothing
|
| 1944 | 1960 | |
| 1961 | +-- | Look up the module of this name provided by a /visible/ unit, even when
|
|
| 1962 | +-- that module is hidden, i.e. is not in its unit's @exposed-modules@.
|
|
| 1963 | +--
|
|
| 1964 | +-- This consults unit metadata only. Unlike "GHC.Unit.Finder", it does not
|
|
| 1965 | +-- look for the module's interface file on disk, so it can answer \"which unit
|
|
| 1966 | +-- provides this module?\" without requiring that unit to have been built yet.
|
|
| 1967 | +--
|
|
| 1968 | +-- An exposed module always takes precedence over a hidden one, and a module
|
|
| 1969 | +-- of a hidden unit is never returned.
|
|
| 1970 | +lookupModuleEvenIfHidden :: UnitState -> ModuleName -> Maybe Module
|
|
| 1971 | +lookupModuleEvenIfHidden pkgs mod_name =
|
|
| 1972 | + case lookupModuleWithSuggestions pkgs mod_name NoPkgQual of
|
|
| 1973 | + LookupFound m _ -> Just m
|
|
| 1974 | + LookupHidden _ mods_hidden
|
|
| 1975 | + | [m] <- [ m | (m, ModHidden HiddenModInVisibleUnit) <- mods_hidden ]
|
|
| 1976 | + -> Just m
|
|
| 1977 | + | otherwise
|
|
| 1978 | + -> Nothing
|
|
| 1979 | + LookupMultiple {} -> Nothing
|
|
| 1980 | + LookupUnusable {} -> Nothing
|
|
| 1981 | + LookupNotFound {} -> Nothing
|
|
| 1982 | + |
|
| 1945 | 1983 | lookupPluginModuleWithSuggestions :: UnitState
|
| 1946 | 1984 | -> ModuleName
|
| 1947 | 1985 | -> PkgQual
|
| ... | ... | @@ -1970,7 +2008,7 @@ lookupModuleWithSuggestions' pkgs mod_map name mb_pn |
| 1970 | 2008 | let origin = filterOrigin mb_pn (mod_unit m) origin0
|
| 1971 | 2009 | x = (m, origin)
|
| 1972 | 2010 | in case origin of
|
| 1973 | - ModHidden
|
|
| 2011 | + ModHidden {}
|
|
| 1974 | 2012 | -> (hidden_pkg, x:hidden_mod, unusable, exposed)
|
| 1975 | 2013 | ModUnusable _
|
| 1976 | 2014 | -> (hidden_pkg, hidden_mod, x:unusable, exposed)
|
| ... | ... | @@ -2003,8 +2041,8 @@ lookupModuleWithSuggestions' pkgs mod_map name mb_pn |
| 2003 | 2041 | filterOrigin (OtherPkg u) pkg o =
|
| 2004 | 2042 | let match_pkg p = u == unitId p
|
| 2005 | 2043 | in case o of
|
| 2006 | - ModHidden
|
|
| 2007 | - | match_pkg pkg -> ModHidden
|
|
| 2044 | + ModHidden {}
|
|
| 2045 | + | match_pkg pkg -> o
|
|
| 2008 | 2046 | | otherwise -> mempty
|
| 2009 | 2047 | ModUnusable _
|
| 2010 | 2048 | | match_pkg pkg -> o
|
| ... | ... | @@ -219,7 +219,6 @@ Library |
| 219 | 219 | , GHC.Integer.Logarithms
|
| 220 | 220 | , GHC.IsList
|
| 221 | 221 | , GHC.Ix
|
| 222 | - , GHC.Essentials
|
|
| 223 | 222 | , GHC.List
|
| 224 | 223 | , GHC.Maybe
|
| 225 | 224 | , GHC.MVar
|
| ... | ... | @@ -307,6 +306,7 @@ Library |
| 307 | 306 | |
| 308 | 307 | other-modules:
|
| 309 | 308 | Data.List.NubOrdSet
|
| 309 | + GHC.Essentials
|
|
| 310 | 310 | System.CPUTime.Unsupported
|
| 311 | 311 | System.CPUTime.Utils
|
| 312 | 312 | if os(windows)
|
| ... | ... | @@ -68,7 +68,6 @@ ignoredModules = |
| 68 | 68 | map mkModuleName $ concat
|
| 69 | 69 | [ unstableModules
|
| 70 | 70 | , platformDependentModules
|
| 71 | - , internalModules
|
|
| 72 | 71 | ]
|
| 73 | 72 | where
|
| 74 | 73 | unstableModules =
|
| ... | ... | @@ -81,8 +80,6 @@ ignoredModules = |
| 81 | 80 | , "GHC.Num.Backend"
|
| 82 | 81 | , "GHC.Num.Backend.Selected"
|
| 83 | 82 | ]
|
| 84 | - internalModules =
|
|
| 85 | - [ "GHC.Essentials" ]
|
|
| 86 | 83 | |
| 87 | 84 | ignoredOccNames :: [OccName]
|
| 88 | 85 | ignoredOccNames =
|