Rodrigo Mesquita pushed to branch wip/spj-reinstallable-base2 at Glasgow Haskell Compiler / GHC
Commits:
-
a2ef5577
by Rodrigo Mesquita at 2026-06-09T17:22:09+01:00
-
79bcda2c
by Rodrigo Mesquita at 2026-06-09T17:22:45+01:00
-
17bc7b47
by Rodrigo Mesquita at 2026-06-09T17:22:48+01:00
-
ab9c2bc4
by Rodrigo Mesquita at 2026-06-11T11:52:46+01:00
-
12153266
by Rodrigo Mesquita at 2026-06-11T11:54:36+01:00
-
88fe754d
by Rodrigo Mesquita at 2026-06-11T16:02:05+01:00
-
5943ac8c
by Rodrigo Mesquita at 2026-06-11T16:06:53+01:00
13 changed files:
- changelog.d/refactor-known-names
- compiler/GHC/HsToCore.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Unit/External.hs
- compiler/GHC/Unit/Module/Deps.hs
- + testsuite/tests/driver/T27013c/Makefile
- + testsuite/tests/driver/T27013c/T27013c.stdout
- + testsuite/tests/driver/T27013c/X.hs
- + testsuite/tests/driver/T27013c/all.T
Changes:
| ... | ... | @@ -5,7 +5,13 @@ synopsis: Completely refactor the handling of "known entities". The goal is to |
| 5 | 5 | itself. This is a major step along the path to making `base` into an ordinary
|
| 6 | 6 | re-installable library.
|
| 7 | 7 | |
| 8 | - Mostly this change is only visible to authors of modules in `ghc-internal` or
|
|
| 9 | - `base`.
|
|
| 8 | + Mostly this change is only visible to authors of modules in `ghc-internal` or `base`.
|
|
| 9 | + |
|
| 10 | + Since the known-names are no longer fully wired in to the compiler, GHCi must
|
|
| 11 | + be able to find `base` for all the known-names like `print` and `IO` to be
|
|
| 12 | + available. Therefore `ghci -hide-all-packages`, which hides `base` from ghci,
|
|
| 13 | + no longer works. One must use `ghci -hide-all-packages -package base` to
|
|
| 14 | + bring in the known-names from base.
|
|
| 15 | + |
|
| 10 | 16 | issues: #27013
|
| 11 | 17 | mrs: !15899 |
| ... | ... | @@ -99,7 +99,7 @@ import Data.IORef |
| 99 | 99 | import GHC.Iface.Make (mkRecompUsageInfo)
|
| 100 | 100 | import GHC.Runtime.Interpreter (interpreterProfiled)
|
| 101 | 101 | import GHC.Types.Unique.FM
|
| 102 | -import GHC.Iface.Load (KnownEntitySource(..), lookupKnownKeyName)
|
|
| 102 | +import GHC.Iface.Load (KnownEntitySource(..), lookupKnownKeyName, lookupKnownKeysModule)
|
|
| 103 | 103 | import GHC.HsToCore.Types (DsGblEnv(..))
|
| 104 | 104 | |
| 105 | 105 | {-
|
| ... | ... | @@ -220,11 +220,13 @@ deSugar hsc_env |
| 220 | 220 | ; endPassHscEnvIO hsc_env name_ppr_ctx CoreDesugar ds_binds ds_rules_for_imps
|
| 221 | 221 | |
| 222 | 222 | ; let pluginModules = map lpModule (loadedPlugins (hsc_plugins hsc_env))
|
| 223 | - home_unit = hsc_home_unit hsc_env
|
|
| 223 | + home_unit = hsc_home_unit hsc_env
|
|
| 224 | + ; essentials_mod <- liftIO $ lookupKnownKeysModule hsc_env dflags
|
|
| 224 | 225 | ; let deps = mkDependencies home_unit
|
| 225 | 226 | (tcg_mod tcg_env)
|
| 226 | 227 | (tcg_imports tcg_env)
|
| 227 | 228 | (map mi_module pluginModules)
|
| 229 | + (moduleUnitId <$> essentials_mod)
|
|
| 228 | 230 | |
| 229 | 231 | ; safe_mode <- finalSafeMode dflags tcg_env
|
| 230 | 232 |
| ... | ... | @@ -24,7 +24,7 @@ module GHC.Iface.Load ( |
| 24 | 24 | lookupKnownKeyThing, lookupKnownKeyName,
|
| 25 | 25 | lookupKnownOccThing, lookupKnownOccName,
|
| 26 | 26 | loadKnownKeyOccMaps, lookupKnownGRE,
|
| 27 | - lookupKnownKeysMap,
|
|
| 27 | + lookupKnownKeysMap, lookupKnownKeysModule,
|
|
| 28 | 28 | |
| 29 | 29 | -- RnM/TcM functions
|
| 30 | 30 | loadModuleInterface, loadModuleInterfaces,
|
| ... | ... | @@ -283,7 +283,7 @@ loadKnownKeyOccMaps :: IfM lcl KnownKeyNameMaps |
| 283 | 283 | loadKnownKeyOccMaps
|
| 284 | 284 | = do { eps <- getEps
|
| 285 | 285 | ; case eps_known_keys eps of {
|
| 286 | - Just kk_maps -> return kk_maps ;
|
|
| 286 | + Just (kk_maps, _) -> return kk_maps ;
|
|
| 287 | 287 | Nothing ->
|
| 288 | 288 | |
| 289 | 289 | -- We don't have a KnownKeyOccMap yet, so create it
|
| ... | ... | @@ -310,7 +310,7 @@ loadKnownKeyOccMaps |
| 310 | 310 | , nm <- availNames avail ]
|
| 311 | 311 | |
| 312 | 312 | -- Record the KnownKeyOccMap in the EPS, so we will find it next time
|
| 313 | - ; updateEps_ (\eps -> eps { eps_known_keys = Just (kk_map, occ_map) })
|
|
| 313 | + ; updateEps_ (\eps -> eps { eps_known_keys = Just ((kk_map, occ_map), mi_module iface) })
|
|
| 314 | 314 | |
| 315 | 315 | #ifdef DEBUG
|
| 316 | 316 | ; case checkKnownKeyNamesIface kk_map of
|
| ... | ... | @@ -355,6 +355,17 @@ checkKnownKeyNamesIface known_key_names_occ_map |
| 355 | 355 | Just name -> getOccName name /= occ
|
| 356 | 356 | #endif
|
| 357 | 357 | |
| 358 | +-- | Lookup the module exporting the canonical known-entities definitions (GHC.Essentials)
|
|
| 359 | +lookupKnownKeysModule :: HscEnv -> DynFlags {-^ Module dyn flags -} -> IO (Maybe Module)
|
|
| 360 | +lookupKnownKeysModule hsc_env dflags = do
|
|
| 361 | + found_essentials <- findImportedModule hsc_env eSSENTIALS_NAME NoPkgQual
|
|
| 362 | + let rebindable_kn = gopt Opt_RebindableKnownNames dflags
|
|
| 363 | + let essentials_uid
|
|
| 364 | + | rebindable_kn = Nothing
|
|
| 365 | + | Found _ mod <- found_essentials = Just mod
|
|
| 366 | + | otherwise = Nothing
|
|
| 367 | + return essentials_uid
|
|
| 368 | + |
|
| 358 | 369 | {- *********************************************************************
|
| 359 | 370 | * *
|
| 360 | 371 | * Global things
|
| ... | ... | @@ -238,16 +238,18 @@ mkIfaceTc hsc_env safe_mode mod_details mod_summary mb_program |
| 238 | 238 | tcg_fix_env = fix_env,
|
| 239 | 239 | tcg_warns = warns
|
| 240 | 240 | }
|
| 241 | - = do
|
|
| 242 | - let pluginModules = map lpModule (loadedPlugins (hsc_plugins hsc_env))
|
|
| 243 | - let home_unit = hsc_home_unit hsc_env
|
|
| 241 | + = do let pluginModules = map lpModule (loadedPlugins (hsc_plugins hsc_env))
|
|
| 242 | + let home_unit = hsc_home_unit hsc_env
|
|
| 243 | + let dflags = ms_hspp_opts mod_summary
|
|
| 244 | + essentials_mod <- liftIO $ lookupKnownKeysModule hsc_env dflags
|
|
| 244 | 245 | let deps = mkDependencies home_unit
|
| 245 | 246 | (tcg_mod tc_result)
|
| 246 | 247 | (tcg_imports tc_result)
|
| 247 | 248 | (map mi_module pluginModules)
|
| 249 | + (moduleUnitId <$> essentials_mod)
|
|
| 248 | 250 | |
| 249 | 251 | usage <- mkRecompUsageInfo hsc_env tc_result
|
| 250 | - docs <- extractDocs (ms_hspp_opts mod_summary) tc_result
|
|
| 252 | + docs <- extractDocs dflags tc_result
|
|
| 251 | 253 | self_recomp <- traverse (mkSelfRecomp hsc_env this_mod (ms_hs_hash mod_summary)) usage
|
| 252 | 254 | |
| 253 | 255 | let partial_iface = mkIface_ hsc_env
|
| ... | ... | @@ -126,7 +126,7 @@ getImportEdges dflags buf filename source_filename = do |
| 126 | 126 | mkPrelImports :: ModuleName
|
| 127 | 127 | -> Bool -> [LImportDecl GhcPs]
|
| 128 | 128 | -> [LImportDecl GhcPs]
|
| 129 | --- Construct the implicit declaration "import Prelude" (or not)
|
|
| 129 | +-- ^ Construct the implicit declaration "import Prelude" (or not)
|
|
| 130 | 130 | --
|
| 131 | 131 | -- NB: opt_NoImplicitPrelude is slightly different to import Prelude ();
|
| 132 | 132 | -- because the former doesn't even look at Prelude.hi for instance
|
| ... | ... | @@ -473,28 +473,28 @@ tcRnImports hsc_env import_decls |
| 473 | 473 | ; gbl_env <- getGblEnv
|
| 474 | 474 | ; let unitId = homeUnitId $ hsc_home_unit hsc_env
|
| 475 | 475 | mnwib = GWIB (moduleName this_mod)(hscSourceToIsBoot (tcg_src gbl_env))
|
| 476 | - ; -- We want instance declarations from all home-package
|
|
| 477 | - -- modules below this one, including boot modules, except
|
|
| 478 | - -- ourselves. The 'except ourselves' is so that we don't
|
|
| 479 | - -- get the instances from this module's hs-boot file. This
|
|
| 480 | - -- filtering also ensures that we don't see instances from
|
|
| 481 | - -- modules batch (@--make@) compiled before this one, but
|
|
| 482 | - -- which are not below this one.
|
|
| 483 | - ; (home_insts, home_fam_insts) <- liftIO $
|
|
| 484 | - hugInstancesBelow hsc_env unitId mnwib
|
|
| 485 | - |
|
| 486 | - -- We use 'unsafeInterleaveIO' to avoid redundant memory allocations
|
|
| 487 | - -- See Note [Lazily loading COMPLETE pragmas] from GHC.HsToCore.Monad
|
|
| 488 | - -- and see https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14274#note_620545
|
|
| 489 | - ; completeSigsBelow <- liftIO $ unsafeInterleaveIO $
|
|
| 490 | - hugCompleteSigsBelow hsc_env unitId mnwib
|
|
| 491 | - |
|
| 492 | - -- Record boot-file info in the EPS, so that it's
|
|
| 493 | - -- visible to loadHiBootInterface in tcRnSrcDecls,
|
|
| 494 | - -- and any other incrementally-performed imports
|
|
| 495 | - ; when (isOneShot (ghcMode (hsc_dflags hsc_env))) $ do {
|
|
| 496 | - updateEps_ $ \eps -> eps { eps_is_boot = imp_boot_mods imports }
|
|
| 497 | - }
|
|
| 476 | + -- We want instance declarations from all home-package
|
|
| 477 | + -- modules below this one, including boot modules, except
|
|
| 478 | + -- ourselves. The 'except ourselves' is so that we don't
|
|
| 479 | + -- get the instances from this module's hs-boot file. This
|
|
| 480 | + -- filtering also ensures that we don't see instances from
|
|
| 481 | + -- modules batch (@--make@) compiled before this one, but
|
|
| 482 | + -- which are not below this one.
|
|
| 483 | + ; (home_insts, home_fam_insts) <- liftIO $
|
|
| 484 | + hugInstancesBelow hsc_env unitId mnwib
|
|
| 485 | + |
|
| 486 | + -- We use 'unsafeInterleaveIO' to avoid redundant memory allocations
|
|
| 487 | + -- See Note [Lazily loading COMPLETE pragmas] from GHC.HsToCore.Monad
|
|
| 488 | + -- and see https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14274#note_620545
|
|
| 489 | + ; completeSigsBelow <- liftIO $ unsafeInterleaveIO $
|
|
| 490 | + hugCompleteSigsBelow hsc_env unitId mnwib
|
|
| 491 | + |
|
| 492 | + -- Record boot-file info in the EPS, so that it's
|
|
| 493 | + -- visible to loadHiBootInterface in tcRnSrcDecls,
|
|
| 494 | + -- and any other incrementally-performed imports
|
|
| 495 | + ; when (isOneShot (ghcMode (hsc_dflags hsc_env))) $ do {
|
|
| 496 | + updateEps_ $ \eps -> eps { eps_is_boot = imp_boot_mods imports }
|
|
| 497 | + }
|
|
| 498 | 498 | |
| 499 | 499 | -- Update the gbl env
|
| 500 | 500 | ; updGblEnv ( \ gbl ->
|
| ... | ... | @@ -217,7 +217,7 @@ lookupKnownKeyGlobal hsc_env key = do |
| 217 | 217 | eps <- hscEPS hsc_env
|
| 218 | 218 | case eps_known_keys eps of
|
| 219 | 219 | Nothing -> pprPanic "lookupKnownKeyGlobal" (text "eps_known_keys not initialized")
|
| 220 | - Just (kk_map, _) -> case lookupKnownKeysMap kk_map key of
|
|
| 220 | + Just ((kk_map, _), _) -> case lookupKnownKeysMap kk_map key of
|
|
| 221 | 221 | Succeeded name -> lookupGlobal hsc_env name
|
| 222 | 222 | Failed err -> pprPanic "lookupKnownKeyGlobal" (pprDiagnostic err)
|
| 223 | 223 | |
| ... | ... | @@ -1116,6 +1116,7 @@ tcGetDefaultTys :: TcM (DefaultEnv, -- Default classes and types |
| 1116 | 1116 | Bool) -- True <=> Use extended defaulting rules
|
| 1117 | 1117 | tcGetDefaultTys
|
| 1118 | 1118 | = do { dflags <- getDynFlags
|
| 1119 | + ; hsc_env <- getTopEnv
|
|
| 1119 | 1120 | ; let ovl_strings = xopt LangExt.OverloadedStrings dflags
|
| 1120 | 1121 | extended_defaults = xopt LangExt.ExtendedDefaultRules dflags
|
| 1121 | 1122 | -- See also #1974
|
| ... | ... | @@ -1128,11 +1129,17 @@ tcGetDefaultTys |
| 1128 | 1129 | ; user_defaults <- getDeclaredDefaultTys -- User-supplied defaults
|
| 1129 | 1130 | ; this_module <- tcg_mod <$> getGblEnv
|
| 1130 | 1131 | ; let this_unit = moduleUnit this_module
|
| 1131 | - ; if this_unit == ghcInternalUnit -- if we wanted, this needn't be about ghc-internal
|
|
| 1132 | - -- see Remark [No built-in defaults in ghc-internal]
|
|
| 1133 | - -- in Note [Builtin class defaults] in GHC.Tc.Utils.Env
|
|
| 1134 | - then return (user_defaults, extended_defaults)
|
|
| 1135 | - else do
|
|
| 1132 | + ; essentials_mod <- liftIO $ lookupKnownKeysModule hsc_env dflags
|
|
| 1133 | + ; case essentials_mod of
|
|
| 1134 | + Nothing ->
|
|
| 1135 | + -- If GHC.Essentials isn't available at all (e.g. -hide-all-packages),
|
|
| 1136 | + -- don't add the built-in defaulting, bc e.g. Num is a known-entity.
|
|
| 1137 | + return (user_defaults, extended_defaults)
|
|
| 1138 | + _ | this_unit == ghcInternalUnit ->
|
|
| 1139 | + -- see Remark [No built-in defaults in ghc-internal]
|
|
| 1140 | + -- in Note [Builtin class defaults] in GHC.Tc.Utils.Env
|
|
| 1141 | + return (user_defaults, extended_defaults)
|
|
| 1142 | + _ -> do
|
|
| 1136 | 1143 | -- Not one of the built-in units
|
| 1137 | 1144 | -- @default Num (Integer, Double)@, plus extensions
|
| 1138 | 1145 | { extDef <- if extended_defaults
|
| ... | ... | @@ -153,7 +153,9 @@ data ExternalPackageState |
| 153 | 153 | -- See Note [Interface Files with Core Definitions]
|
| 154 | 154 | eps_iface_bytecode :: !(ModuleEnv (IO Linkable)),
|
| 155 | 155 | |
| 156 | - eps_known_keys :: Maybe KnownKeyNameMaps, -- ^ See Note [Overview of known entities]
|
|
| 156 | + eps_known_keys :: Maybe (KnownKeyNameMaps, Module),
|
|
| 157 | + -- ^ See Note [Overview of known entities].
|
|
| 158 | + -- Caches the 'Module' where known entities are defined.
|
|
| 157 | 159 | |
| 158 | 160 | eps_inst_env :: !PackageInstEnv, -- ^ The total 'InstEnv' accumulated
|
| 159 | 161 | -- from all the external-package modules
|
| ... | ... | @@ -174,8 +174,9 @@ instance Outputable IfaceImportLevel where |
| 174 | 174 | -- a dependencies information for the module being compiled.
|
| 175 | 175 | --
|
| 176 | 176 | -- The fourth argument is a list of plugin modules.
|
| 177 | -mkDependencies :: HomeUnit -> Module -> ImportAvails -> [Module] -> Dependencies
|
|
| 178 | -mkDependencies home_unit mod imports plugin_mods =
|
|
| 177 | +-- The fifth argument is the unit-id of GHC.Essentials, unless -frebindable-known-names.
|
|
| 178 | +mkDependencies :: HomeUnit -> Module -> ImportAvails -> [Module] -> Maybe UnitId -> Dependencies
|
|
| 179 | +mkDependencies home_unit mod imports plugin_mods messentials_pkg =
|
|
| 179 | 180 | let (home_plugins, external_plugins) = partition (isHomeUnit home_unit . moduleUnit) plugin_mods
|
| 180 | 181 | plugin_units = Set.fromList (map (toUnitId . moduleUnit) external_plugins)
|
| 181 | 182 | all_direct_mods = foldr (\(s, mn) m -> extendInstalledModuleEnv m mn (s, (GWIB (moduleName mn) NotBoot)))
|
| ... | ... | @@ -202,7 +203,14 @@ mkDependencies home_unit mod imports plugin_mods = |
| 202 | 203 | -- We must also remove self-references from imp_orphs. See
|
| 203 | 204 | -- Note [Module self-dependency]
|
| 204 | 205 | |
| 205 | - direct_pkgs = Set.map (\(lvl, uid) -> (IfaceImportLevel lvl, uid)) (imp_dep_direct_pkgs imports)
|
|
| 206 | + direct_pkgs = add_essentials_pkg $
|
|
| 207 | + Set.map (\(lvl, uid) -> (IfaceImportLevel lvl, uid)) (imp_dep_direct_pkgs imports)
|
|
| 208 | + |
|
| 209 | + -- Add the GHC.Essentials package to direct deps unless -frebindable-known-names is on
|
|
| 210 | + -- (the modgraph has edges to GHC.Essentials similarly, see `getImportEdges` in GHC.Parser.Header)
|
|
| 211 | + add_essentials_pkg = case messentials_pkg of
|
|
| 212 | + Nothing -> id
|
|
| 213 | + Just essentials_uid -> Set.insert (IfaceImportLevel NormalLevel, essentials_uid)
|
|
| 206 | 214 | |
| 207 | 215 | -- Set the packages required to be Safe according to Safe Haskell.
|
| 208 | 216 | -- See Note [Tracking Trust Transitively] in GHC.Rename.Names
|
| 1 | +TOP=../../..
|
|
| 2 | +include $(TOP)/mk/boilerplate.mk
|
|
| 3 | +include $(TOP)/mk/test.mk
|
|
| 4 | + |
|
| 5 | +# Test that compiling X.hs without implicit Prelude does not recompile X the
|
|
| 6 | +# second time or third time. In !15899, X.hs was recompiled because of an
|
|
| 7 | +# incorrect "GHC.Essentials package changed"
|
|
| 8 | +clean:
|
|
| 9 | + rm -f *.o *.hi
|
|
| 10 | + |
|
| 11 | +T27013c: clean
|
|
| 12 | + '$(TEST_HC)' $(TEST_HC_OPTS) --make X.hs
|
|
| 13 | + '$(TEST_HC)' $(TEST_HC_OPTS) --make X.hs
|
|
| 14 | + '$(TEST_HC)' $(TEST_HC_OPTS) --make X.hs |
| 1 | +[1 of 1] Compiling X ( X.hs, X.o ) |
| 1 | +{-# LANGUAGE NoImplicitPrelude #-}
|
|
| 2 | +module X where
|
|
| 3 | +x = x |
| 1 | +test('T27013c', [extra_files(['X.hs'])],
|
|
| 2 | + makefile_test, []) |