Simon Peyton Jones pushed to branch wip/spj-reinstallable-base at Glasgow Haskell Compiler / GHC Commits: 88d760d9 by Simon Peyton Jones at 2026-03-15T00:53:33+00:00 Progress It compiles - - - - - 28 changed files: - compiler/GHC/Builtin/Names.hs - compiler/GHC/Builtin/Names/TH.hs - compiler/GHC/Builtin/Utils.hs - compiler/GHC/Driver/Env/KnotVars.hs - compiler/GHC/Driver/Flags.hs - compiler/GHC/HsToCore/Monad.hs - compiler/GHC/HsToCore/Pmc/Desugar.hs - compiler/GHC/HsToCore/Quote.hs - compiler/GHC/Iface/Env.hs - − compiler/GHC/Iface/Env.hs-boot - compiler/GHC/Iface/Load.hs - compiler/GHC/Iface/Tidy.hs - compiler/GHC/IfaceToCore.hs - compiler/GHC/Rename/Env.hs - compiler/GHC/Tc/Deriv/Generics.hs - compiler/GHC/Tc/Gen/Splice.hs - compiler/GHC/Tc/Instance/Typeable.hs - compiler/GHC/Tc/TyCl/Build.hs - compiler/GHC/Tc/Types.hs - compiler/GHC/Tc/Utils/Env.hs - compiler/GHC/Tc/Utils/Instantiate.hs - compiler/GHC/Tc/Utils/Monad.hs - compiler/GHC/Types/Name/Cache.hs - compiler/GHC/Unit/External.hs - libraries/base/base.cabal.in - libraries/ghc-internal/ghc-internal.cabal.in - libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs - libraries/ghc-internal/src/GHC/Internal/Real.hs Changes: ===================================== compiler/GHC/Builtin/Names.hs ===================================== @@ -188,8 +188,8 @@ names with uniques. These ones are the *non* wired-in ones. The wired in ones are defined in GHC.Builtin.Types etc. -} -basicKnownKeyOccs :: [(OccName, Unique)] -basicKnownKeyOccs +basicKnownKeyTable :: [(OccName, Unique)] +basicKnownKeyTable = [ (mkTcOcc "Rational", rationalTyConKey) ] basicKnownKeyNames :: [Name] -- See Note [Known-key names] ===================================== compiler/GHC/Builtin/Names/TH.hs ===================================== @@ -25,8 +25,8 @@ import Language.Haskell.Syntax.Module.Name -- 2) Make a "Name" -- 3) Add the name to templateHaskellNames -templateHaskellOccs :: [(OccName,Unique)] -templateHaskellOccs = [] +thKnownKeyTable :: [(OccName,Unique)] +thKnownKeyTable = [] templateHaskellNames :: [Name] -- The names that are implicitly mentioned by ``bracket'' ===================================== compiler/GHC/Builtin/Utils.hs ===================================== @@ -28,7 +28,7 @@ module GHC.Builtin.Utils ( -- if you find yourself wanting to look at it you might consider using -- 'lookupKnownKeyName' or 'isKnownKeyName'. knownKeyNames, - KnownKeyOccMap, knownKeyOccMap, + knownKeyOccMap, knownKeyUniqMap, -- * Miscellaneous wiredInIds, ghcPrimIds, @@ -54,7 +54,7 @@ import GHC.Builtin.PrimOps.Ids import GHC.Builtin.Types import GHC.Builtin.Types.Literals ( typeNatTyCons ) import GHC.Builtin.Types.Prim -import GHC.Builtin.Names.TH ( templateHaskellNames, templateHaskellOccs ) +import GHC.Builtin.Names.TH ( templateHaskellNames, thKnownKeyTable ) import GHC.Builtin.Names import GHC.Core.ConLike ( ConLike(..) ) @@ -205,12 +205,13 @@ isKnownKeyName :: Name -> Bool isKnownKeyName n = isJust (knownUniqueName $ nameUnique n) || elemUFM n knownKeysMap -type KnownKeyOccMap = OccEnv Name - -- See Note [Overview of known-key Names] - -- | `knownKeyOccMap` maps the OccName of a known-key to its Unique knownKeyOccMap :: OccEnv Unique -knownKeyOccMap = mkOccEnv (basicKnownKeyOccs ++ templateHaskellOccs) +knownKeyOccMap = mkOccEnv (basicKnownKeyTable ++ thKnownKeyTable) + +knownKeyUniqMap :: UniqFM Unique OccName +knownKeyUniqMap = listToUFM [ (uniq, occ) + | (occ, uniq) <- basicKnownKeyTable ++ thKnownKeyTable ] -- | Maps 'Unique's to known-key names. -- ===================================== compiler/GHC/Driver/Env/KnotVars.hs ===================================== @@ -16,9 +16,12 @@ import GHC.Utils.Outputable -- See Note [Why is KnotVars not a ModuleEnv] -- See Note [KnotVars invariants] -data KnotVars a = KnotVars { kv_domain :: [Module] -- Domain of the function , Note [KnotVars: Why store the domain?] - -- Invariant: kv_lookup is surjective relative to kv_domain +data KnotVars a = KnotVars { kv_domain :: [Module] + -- Domain of kv_lookup + -- See Note [KnotVars: Why store the domain?] + , kv_lookup :: Module -> Maybe a -- Lookup function + -- Invariant: kv_lookup is surjective relative to kv_domain } | NoKnotVars deriving Functor ===================================== compiler/GHC/Driver/Flags.hs ===================================== @@ -150,6 +150,7 @@ extensionName = \case LangExt.ImplicitParams -> "ImplicitParams" LangExt.ImplicitPrelude -> "ImplicitPrelude" LangExt.ImplicitKnownKeyNames -> "ImplicitKnownKeyNames" + LangExt.DefinesKnownKeyNames -> "DefinesKnownKeyNames" LangExt.ScopedTypeVariables -> "ScopedTypeVariables" LangExt.AllowAmbiguousTypes -> "AllowAmbiguousTypes" LangExt.UnboxedTuples -> "UnboxedTuples" ===================================== compiler/GHC/HsToCore/Monad.hs ===================================== @@ -81,6 +81,7 @@ import GHC.Core.Type import GHC.Core.Multiplicity import GHC.IfaceToCore +import GHC.Iface.Load( lookupKnownKeyThing ) import GHC.Tc.Utils.Monad @@ -117,7 +118,11 @@ import GHC.Utils.Error import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Misc( HasDebugCallStack ) + +import qualified GHC.LanguageExtensions as LangExt + import qualified GHC.Data.Strict as Strict +import GHC.Data.Maybe import GHC.Data.OrdList import Data.IORef @@ -396,16 +401,22 @@ mkDsEnvs :: UnitEnv -> Module -> GlobalRdrEnv -> TypeEnv -> FamInstEnv mkDsEnvs unit_env mod rdr_env type_env fam_inst_env ptc msg_var cc_st_var statics_var next_wrapper_num complete_matches = let if_genv = IfGblEnv { if_doc = text "mkDsEnvs" - -- Failing tests here are `ghci` and `T11985` if you get this wrong. - -- this is very very "at a distance" because the reason for this check is that the type_env in interactive - -- mode is the smushed together of all the interactive modules. - -- See Note [Why is KnotVars not a ModuleEnv] - , if_rec_types = KnotVars [mod] (\that_mod -> if that_mod == mod || isInteractiveModule mod - then Just (return type_env) - else Nothing) } + , if_rec_types = KnotVars [mod] knot_var_fun } + -- Failing tests here are `ghci` and `T11985` if you get this wrong. + -- This is very very "at a distance" because the reason for this check + -- is that the type_env in interactive mode is the smushed together + -- of all the interactive modules. + -- See Note [Why is KnotVars not a ModuleEnv] + + knot_var_fun :: Module -> Maybe (IfG TypeEnv) + knot_var_fun that_mod + | that_mod == mod || isInteractiveModule mod = Just (return type_env) + | otherwise = Nothing + if_lenv = mkIfLclEnv mod (text "GHC error in desugarer lookup in" <+> ppr mod) NotBoot real_span = realSrcLocSpan (mkRealSrcLoc (moduleNameFS (moduleName mod)) 1 1) + gbl_env = DsGblEnv { ds_mod = mod , ds_fam_inst_env = fam_inst_env , ds_gbl_rdr_env = rdr_env @@ -426,7 +437,7 @@ mkDsEnvs unit_env mod rdr_env type_env fam_inst_env ptc msg_var cc_st_var dsToIfL :: IfL a -> DsM a -- Run an Iface action in the Ds monad -dsToIfl iface_action +dsToIfL iface_action = do { env <- getGblEnv ; setEnvs (ds_if_env env) iface_action } @@ -554,28 +565,21 @@ mkNamePprCtxDs = ds_name_ppr_ctx <$> getGblEnv instance MonadThings (IOEnv (Env DsGblEnv DsLclEnv)) where lookupThing = dsLookupGlobal -dsLookupKnownKey :: OccName -> DsM TyThing -dsLookupKnownKey occ - = do { normal_path <- xoptM ImplicitKnownKeyNames - ; if normal_path - then dsToIfL $ - lookupImportedKnownKey occ - else - lookupKnownKeyOcc occ - } - -dsLookupKnownKeyOcc :: OccName -> DsM TyThing --- Look up the known-key OccName in the current top-level GlobalRdrEnv --- If we get a unique hit, use it; if not, panic. -dsLookupKnownKeyOcc occ - = do { gbl_rdr_env <- dsGetGlobalRdrEnv - ; case lookupGRE gbl_rdr_env (lookupOccName occ SameNameSpace) of - [name] -> dsLookupGlobal name - gres -> pprPanic "lookupKnownKeyOcc" (ppr occ $$ ppr gres) } - -dsLookupKnownKeyTyCon :: Name -> DsM TyCon -dsLookupKnownKeyTyCon name - = tyThingTyCon <$> dsLookupKnownKey name +dsLookupKnownKey :: Unique -> DsM TyThing +dsLookupKnownKey uniq + = do { normal_path <- xoptM LangExt.ImplicitKnownKeyNames + ; mb_rdr_env <- if normal_path + then return Nothing + else Just <$> dsGetGlobalRdrEnv + ; dsToIfL $ + do { mb_res <- lookupKnownKeyThing mb_rdr_env uniq + ; case mb_res of + Succeeded thing -> return thing + Failed msg -> failIfM (pprDiagnostic msg) } } + +dsLookupKnownKeyTyCon :: Unique -> DsM TyCon +dsLookupKnownKeyTyCon uniq + = tyThingTyCon <$> dsLookupKnownKey uniq dsLookupGlobal :: Name -> DsM TyThing -- Very like GHC.Tc.Utils.Env.tcLookupGlobal ===================================== compiler/GHC/HsToCore/Pmc/Desugar.hs ===================================== @@ -21,7 +21,7 @@ import GHC.Types.Id import GHC.Core.ConLike import GHC.Types.Name import GHC.Builtin.Types -import GHC.Builtin.Names (rationalTyConName, toListName) +import GHC.Builtin.Names (rationalTyConKey, toListName) import GHC.Types.SrcLoc import GHC.Utils.Outputable import GHC.Utils.Panic @@ -253,7 +253,7 @@ desugarPat x pat = case pat of , (HsFractional f) <- val , negates <- if fl_neg f then 1 else 0 -> do - rat_tc <- dsLookupTyCon rationalTyConName + rat_tc <- dsLookupKnownKeyTyCon rationalTyConKey let rat_ty = mkTyConTy rat_tc return $ Just $ PmLit rat_ty (PmLitOverRat negates f) | otherwise ===================================== compiler/GHC/HsToCore/Quote.hs ===================================== @@ -2351,6 +2351,12 @@ lookupType :: Name -- Name of type constructor (e.g. (M TH.Exp)) lookupType tc_name = do { tc <- lift $ dsLookupTyCon tc_name ; return (mkTyConApp tc []) } +lookupKnownKeyType :: Unique -- Unique of type constructor (e.g. (M TH.Exp)) + -> MetaM Type -- The type +lookupKnownKeyType tc_key + = do { tc <- lift $ dsLookupKnownKeyTyCon tc_key + ; return (mkTyConApp tc []) } + wrapGenSyms :: [GenSymBind] -> Core (M a) -> MetaM (Core (M a)) -- wrapGenSyms [(nm1,id1), (nm2,id2)] y @@ -3086,7 +3092,7 @@ mk_integer :: Integer -> MetaM (HsLit GhcTc) mk_integer i = return $ XLit $ HsInteger NoSourceText i integerTy mk_rational :: FractionalLit -> MetaM (HsLit GhcTc) -mk_rational r = do rat_ty <- lookupType rationalTyConName +mk_rational r = do rat_ty <- lookupKnownKeyType rationalTyConKey return $ XLit $ HsRat r rat_ty mk_string :: FastString -> MetaM (HsLit GhcRn) ===================================== compiler/GHC/Iface/Env.hs ===================================== @@ -41,7 +41,10 @@ import GHC.Types.Avail import GHC.Types.Name.Cache import GHC.Types.Unique.Supply import GHC.Types.SrcLoc +import GHC.Types.Unique +import GHC.Utils.Misc( HasDebugCallStack ) +import GHC.Utils.Panic( callStackDoc ) import GHC.Utils.Outputable import GHC.Utils.Error import GHC.Utils.Logger @@ -59,20 +62,21 @@ import Control.Monad See Also: Note [The Name Cache] in GHC.Types.Name.Cache -} -newGlobalBinder :: Module -> OccName -> SrcSpan -> TcRnIf a b Name +newGlobalBinder :: HasDebugCallStack => Module -> OccName -> Maybe Unique + -> SrcSpan -> TcRnIf a b Name -- Used for source code and interface files, to make the -- Name for a thing, given its Module and OccName -- See Note [The Name Cache] in GHC.Types.Name.Cache -- -- The cache may already have a binding for this thing, --- because we may have seen an occurrence before, but now is the +-- because we may have seen an /occurrence/ before, but now is the -- moment when we know its Module and SrcLoc in their full glory -newGlobalBinder mod occ loc +newGlobalBinder mod occ mb_uniq loc = do { hsc_env <- getTopEnv - ; name <- liftIO $ allocateGlobalBinder (hsc_NC hsc_env) mod occ loc + ; name <- liftIO $ allocateGlobalBinder (hsc_NC hsc_env) mod occ mb_uniq loc ; traceIf (text "newGlobalBinder" <+> - (vcat [ ppr mod <+> ppr occ <+> ppr loc, ppr name])) + vcat [ ppr mod <+> ppr occ <+> ppr loc, ppr name, callStackDoc]) ; return name } newInteractiveBinder :: HscEnv -> OccName -> SrcSpan -> IO Name @@ -80,14 +84,14 @@ newInteractiveBinder :: HscEnv -> OccName -> SrcSpan -> IO Name -- from the interactive context newInteractiveBinder hsc_env occ loc = do let mod = icInteractiveModule (hsc_IC hsc_env) - allocateGlobalBinder (hsc_NC hsc_env) mod occ loc + allocateGlobalBinder (hsc_NC hsc_env) mod occ Nothing loc allocateGlobalBinder :: NameCache - -> Module -> OccName -> SrcSpan + -> Module -> OccName -> Maybe Unique -> SrcSpan -> IO Name -- See Note [The Name Cache] in GHC.Types.Name.Cache -allocateGlobalBinder nc mod occ loc +allocateGlobalBinder nc mod occ mb_uniq loc = updateNameCache nc mod occ $ \cache0 -> do case lookupOrigNameCache cache0 mod occ of -- A hit in the cache! We are at the binding site of the name. @@ -109,17 +113,23 @@ allocateGlobalBinder nc mod occ loc Just name | isWiredInName name -> pure (cache0, name) | otherwise - -> pure (new_cache, name') + -> warnPprTrace wrong_unique "allocateGlobalBinder" (ppr mb_uniq $$ ppr name) $ + pure (new_cache, name') where uniq = nameUnique name name' = mkExternalName uniq mod occ loc -- name' is like name, but with the right SrcSpan new_cache = extendOrigNameCache cache0 mod occ name' + wrong_unique = case mb_uniq of + Nothing -> False + Just kn_uniq -> kn_uniq /= uniq -- Miss in the cache! -- Build a completely new Name, and put it in the cache _ -> do - uniq <- takeUniqFromNameCache nc + uniq <- case mb_uniq of + Just uniq -> return uniq + Nothing -> takeUniqFromNameCache nc let name = mkExternalName uniq mod occ loc let new_cache = extendOrigNameCache cache0 mod occ name pure (new_cache, name) @@ -178,7 +188,7 @@ externaliseName mod name setNameModule :: Maybe Module -> Name -> TcRnIf m n Name setNameModule Nothing n = return n setNameModule (Just m) n = - newGlobalBinder m (nameOccName n) (nameSrcSpan n) + newGlobalBinder m (nameOccName n) Nothing (nameSrcSpan n) {- ************************************************************************ ===================================== compiler/GHC/Iface/Env.hs-boot deleted ===================================== @@ -1,9 +0,0 @@ -module GHC.Iface.Env where - -import GHC.Unit.Module -import GHC.Types.Name.Occurrence -import GHC.Tc.Utils.Monad -import GHC.Types.Name -import GHC.Types.SrcLoc - -newGlobalBinder :: Module -> OccName -> SrcSpan -> TcRnIf a b Name ===================================== compiler/GHC/Iface/Load.hs ===================================== @@ -9,13 +9,14 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE ScopedTypeVariables #-} -- | Loading interface files module GHC.Iface.Load ( -- Importing one thing - tcLookupImported_maybe, importDecl, + importDecl, checkWiredInTyCon, ifCheckWiredInThing, - lookupImportedKnownKey, + lookupKnownKeyThing, loadGlobalName, -- RnM/TcM functions loadModuleInterface, loadModuleInterfaces, @@ -71,6 +72,7 @@ import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Logger +import GHC.Utils.Misc( HasDebugCallStack ) import GHC.Settings.Constants @@ -86,6 +88,7 @@ import GHC.Types.Annotations import GHC.Types.Name import GHC.Types.Name.Cache import GHC.Types.Name.Env +import GHC.Types.Name.Reader import GHC.Types.Avail import GHC.Types.Fixity import GHC.Types.Fixity.Env @@ -94,6 +97,7 @@ import GHC.Types.SourceFile import GHC.Types.SafeHaskell import GHC.Types.TypeEnv import GHC.Types.Unique.DSet +import GHC.Types.Unique.FM( listToUFM, lookupUFM ) import GHC.Types.SrcLoc import GHC.Types.TyThing import GHC.Types.PkgQual @@ -122,10 +126,158 @@ import Data.Function ((&)) import GHC.Unit.Module.Graph import qualified GHC.Unit.Home.Graph as HUG + +{- ********************************************************************* +* * +* Known-key things * +* * +********************************************************************* -} + +lookupKnownKeyThing :: HasDebugCallStack + => Maybe GlobalRdrEnv -> Unique + -> IfM lcl (MaybeErr IfaceMessage TyThing) +lookupKnownKeyThing Nothing uniq + = do { known_key_name_map <- loadKnownKeyOccMap + ; let name = lookupUFM known_key_name_map uniq + `orElse` pprPanic "lookupKnownKeyThing" (ppr uniq) + ; lookupGlobalName name } + +lookupKnownKeyThing (Just gbl_rdr_env) uniq + -- Look up the known-key OccName in the current top-level GlobalRdrEnv + -- If we get a unique hit, use it; if not, panic. + = case lookupGRE gbl_rdr_env (LookupOccName occ SameNameSpace) of + [gre] -> lookupGlobalName (greName gre) + gres -> pprPanic "lookupKnownKeyOcc" (ppr occ $$ ppr gres) + where + occ = lookupUFM knownKeyUniqMap uniq + `orElse` pprPanic "lookupKnownKeyThing" (ppr uniq) + +loadKnownKeyOccMap :: IfM lcl KnownKeyNameMap +loadKnownKeyOccMap + = do { eps <- getEps + ; case eps_known_keys eps of { + Just occ_map -> return occ_map ; + Nothing -> + + -- We don't have a KnownKeyOccMap yet, so create it + -- from the interface file for KnownKeyName + do { hsc_env <- getTopEnv + ; mb_res <- liftIO $ findImportedModule hsc_env kNOWN_KEY_NAMES NoPkgQual + ; iface <- case mb_res of + Found _ mod -> loadInterfaceWithException doc mod ImportBySystem + _ -> panic "loadKnownKeyOccMap" -- ToDo tidy up + + ; let occ_map :: KnownKeyNameMap + occ_map = listToUFM [ (getUnique nm, nm) + | avail <- mi_exports iface + , nm <- availNames avail ] + + -- Record the KnownKeyOccMap in the EPS, so we will find it next time + ; updateEps_ (\eps -> eps { eps_known_keys = Just occ_map }) + + ; return occ_map } } } + where + doc = text "Need interface for KnonwKeyNames" + + +{- ********************************************************************* +* * +* Global things +* * +********************************************************************* -} + +lookupGlobalName :: Name -> IfM lcl (MaybeErr IfaceMessage TyThing) +-- Only works for External Names that have a Module +lookupGlobalName name = loadGlobalName name (nameModule name) + +loadGlobalName :: forall lcl. + Name + -> Module -- Use this for non-External Names (maybe Backpack-related?) + -> IfM lcl (MaybeErr IfaceMessage TyThing) +loadGlobalName name mod + = do { env <- getGblEnv + ; case lookupKnotVars (if_rec_types env) mod of + -- Note [Tying the knot] + Just get_type_env + -> do -- It's defined in a module in the hs-boot loop + { type_env <- setLclEnv () get_type_env -- yuk + ; case lookupNameEnv type_env name of + Just thing -> return (Succeeded thing) + -- See Note [Knot-tying fallback on boot] + Nothing -> via_external + } + + _ -> via_external } + where + via_external = do { hsc_env <- getTopEnv + ; mb_thing <- liftIO (lookupType hsc_env name) + ; case mb_thing of + Just thing -> return (Succeeded thing) + Nothing -> importDecl name } + +-- Note [Tying the knot] +-- ~~~~~~~~~~~~~~~~~~~~~ +-- The if_rec_types field is used when we are compiling M.hs, which indirectly +-- imports Foo.hi, which mentions M.T Then we look up M.T in M's type +-- environment, which is splatted into if_rec_types after we've built M's type +-- envt. +-- +-- This is a dark and complicated part of GHC type checking, with a lot +-- of moving parts. Interested readers should also look at: +-- +-- * Note [Knot-tying typecheckIface] +-- * Note [DFun knot-tying] +-- * Note [hsc_type_env_var hack] +-- * Note [Knot-tying fallback on boot] +-- * Note [Hydrating Modules] +-- +-- There is also a wiki page on the subject, see: +-- +-- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/tying-the-knot + +-- Note [Knot-tying fallback on boot] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- Suppose that you are typechecking A.hs, which transitively imports, +-- via B.hs, A.hs-boot. When we poke on B.hs and discover that it +-- has a reference to a type T from A, what TyThing should we wire +-- it up with? Clearly, if we have already typechecked T and +-- added it into the type environment, we should go ahead and use that +-- type. But what if we haven't typechecked it yet? +-- +-- For the longest time, GHC adopted the policy that this was +-- *an error condition*; that you MUST NEVER poke on B.hs's reference +-- to a T defined in A.hs until A.hs has gotten around to kind-checking +-- T and adding it to the env. However, actually ensuring this is the +-- case has proven to be a bug farm, because it's really difficult to +-- actually ensure this never happens. The problem was especially poignant +-- with type family consistency checks, which eagerly happen before any +-- typechecking takes place. +-- +-- Today, we take a different strategy: if we ever try to access +-- an entity from A which doesn't exist, we just fall back on the +-- definition of A from the hs-boot file. This is complicated in +-- its own way: it means that you may end up with a mix of A.hs and +-- A.hs-boot TyThings during the course of typechecking. We don't +-- think (and have not observed) any cases where this would cause +-- problems, but the hypothetical situation one might worry about +-- is something along these lines in Core: +-- +-- case x of +-- A -> e1 +-- B -> e2 +-- +-- If, when typechecking this, we find x :: T, and the T we are hooked +-- up with is the abstract one from the hs-boot file, rather than the +-- one defined in this module with constructors A and B. But it's hard +-- to see how this could happen, especially because the reference to +-- the constructor (A and B) means that GHC will always typecheck +-- this expression *after* typechecking T. + + {- ************************************************************************ * * -* tcImportDecl is the key function for "faulting in" * +* importDecl is the key function for "faulting in" * * imported things * * ************************************************************************ @@ -148,61 +300,8 @@ where the code that e1 expands to might import some defns that also turn out to be needed by the code that e2 expands to. -} -tcLookupImported_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing) --- Returns (Failed err) if we can't find the interface file for the thing -tcLookupImported_maybe name - = do { hsc_env <- getTopEnv - ; mb_thing <- liftIO (lookupType hsc_env name) - ; case mb_thing of - Just thing -> return (Succeeded thing) - Nothing -> tcImportDecl_maybe name } - -tcImportDecl_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing) --- Entry point for *source-code* uses of importDecl -tcImportDecl_maybe name - | Just thing <- wiredInNameTyThing_maybe name - = do { when (needWiredInHomeIface thing) - (initIfaceTcRn (loadWiredInHomeIface name)) - -- See Note [Loading instances for wired-in things] - ; return (Succeeded thing) } - | otherwise - = initIfaceTcRn (importDecl name) - -lookupImportedKnownKey :: OccName -> IfM lcl (MaybeErr IfaceMessage TyThing) -lookupImportedKnownKey occ - = do { known_key_occ_map <- loadKnownKeyOccMap - ; let name = lookupOccEnv known_key_occ_map occ - `orElse` pprPanic "lookupImportedKnownKey" (ppr occ) - ; importDecl name } - -loadKnownKeyOccMap :: IfM lcl KnownKeyOccMap -loadKnownKeyOccMap - = do { eps <- getEps - ; case eps_known_keys eps of { - Just occ_map -> return occ_map ; - Nothing -> - - -- We don't have a KnownKeyOccMap yet, so created it - -- from the interface file for KnownKeyName - do { hsc_env <- getTopEnv - ; mb_res <- liftIO $ findImportedModule hsc_env kNOWN_KEY_NAMES NoPkgQual - ; iface <- case mb_res of - Found _ mod -> loadInterfaceWithException doc mod ImportBySystem - _ -> panic "loadKnownKeyOccMap" -- ToDo tidy up - - ; let occ_map :: KnownKeyOccMap - occ_map = mkOccEnv [ (getOccName nm, nm) - | avail <- mi_exports iface - , nm <- availNames avail ] - - -- Record the KnownKeyOccMap in the EPS, so we will find it next time - ; updateEps_ (\eps -> eps { eps_known_keys = Just occ_map }) - - ; return occ_map } } } - where - doc = text "Need interface for KnonwKeyNames" -importDecl :: Name -> IfM lcl (MaybeErr IfaceMessage TyThing) +importDecl :: HasDebugCallStack => Name -> IfM lcl (MaybeErr IfaceMessage TyThing) -- Get the TyThing for this Name from an interface file -- It's not a wired-in thing -- the caller caught that importDecl name @@ -222,7 +321,8 @@ importDecl name { eps <- getEps ; case lookupTypeEnv (eps_PTE eps) name of Just thing -> return $ Succeeded thing - Nothing -> return $ Failed $ + Nothing -> pprTrace "importDecl" (ppr name $$ callStackDoc) $ + return $ Failed $ Can'tFindNameInInterface name (filter is_interesting $ nonDetNameEnvElts $ eps_PTE eps) }}} ===================================== compiler/GHC/Iface/Tidy.hs ===================================== @@ -1107,7 +1107,7 @@ tidyTopName mod name_cache maybe_ref occ_env id -- This is necessary because the byte-code generator the byte-code -- generator builds a system-wide Name->BCO symbol table. - | local && external = do new_external_name <- allocateGlobalBinder name_cache mod occ' loc + | local && external = do new_external_name <- allocateGlobalBinder name_cache mod occ' Nothing loc return (occ_env', new_external_name) -- If we want to externalise a currently-local name, check -- whether we have already assigned a unique for it. ===================================== compiler/GHC/IfaceToCore.hs ===================================== @@ -12,7 +12,6 @@ Type checking of type signatures in interface files {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} module GHC.IfaceToCore ( - tcLookupImported_maybe, importDecl, checkWiredInTyCon, tcHiBootIface, typecheckIface, typecheckWholeCoreBindings, tcIfaceDefaults, @@ -33,7 +32,6 @@ import GHC.Prelude import GHC.ByteCode.Types -import GHC.Driver.Env import GHC.Driver.Session import GHC.Driver.Config.Core.Lint ( initLintConfig ) @@ -2046,91 +2044,13 @@ tcIfaceGlobal name = do { ifCheckWiredInThing thing; return thing } | otherwise - = do { env <- getGblEnv - ; cur_mod <- if_mod <$> getLclEnv - ; case lookupKnotVars (if_rec_types env) (fromMaybe cur_mod (nameModule_maybe name)) of - -- Note [Tying the knot] - Just get_type_env - -> do -- It's defined in a module in the hs-boot loop - { type_env <- setLclEnv () get_type_env -- yuk - ; case lookupNameEnv type_env name of - Just thing -> return thing - -- See Note [Knot-tying fallback on boot] - Nothing -> via_external - } - - _ -> via_external } - where - via_external = do - { hsc_env <- getTopEnv - ; mb_thing <- liftIO (lookupType hsc_env name) - ; case mb_thing of { - Just thing -> return thing ; - Nothing -> do - - { mb_thing <- importDecl name -- It's imported; go get it - ; case mb_thing of + = do { mod <- case nameModule_maybe name of + Just mod -> return mod + Nothing -> if_mod <$> getLclEnv + ; mb_thing <- loadGlobalName name mod + ; case mb_thing of Failed err -> failIfM (ppr name <+> pprDiagnostic err) - Succeeded thing -> return thing - }}} - --- Note [Tying the knot] --- ~~~~~~~~~~~~~~~~~~~~~ --- The if_rec_types field is used when we are compiling M.hs, which indirectly --- imports Foo.hi, which mentions M.T Then we look up M.T in M's type --- environment, which is splatted into if_rec_types after we've built M's type --- envt. --- --- This is a dark and complicated part of GHC type checking, with a lot --- of moving parts. Interested readers should also look at: --- --- * Note [Knot-tying typecheckIface] --- * Note [DFun knot-tying] --- * Note [hsc_type_env_var hack] --- * Note [Knot-tying fallback on boot] --- * Note [Hydrating Modules] --- --- There is also a wiki page on the subject, see: --- --- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/tying-the-knot - --- Note [Knot-tying fallback on boot] --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- Suppose that you are typechecking A.hs, which transitively imports, --- via B.hs, A.hs-boot. When we poke on B.hs and discover that it --- has a reference to a type T from A, what TyThing should we wire --- it up with? Clearly, if we have already typechecked T and --- added it into the type environment, we should go ahead and use that --- type. But what if we haven't typechecked it yet? --- --- For the longest time, GHC adopted the policy that this was --- *an error condition*; that you MUST NEVER poke on B.hs's reference --- to a T defined in A.hs until A.hs has gotten around to kind-checking --- T and adding it to the env. However, actually ensuring this is the --- case has proven to be a bug farm, because it's really difficult to --- actually ensure this never happens. The problem was especially poignant --- with type family consistency checks, which eagerly happen before any --- typechecking takes place. --- --- Today, we take a different strategy: if we ever try to access --- an entity from A which doesn't exist, we just fall back on the --- definition of A from the hs-boot file. This is complicated in --- its own way: it means that you may end up with a mix of A.hs and --- A.hs-boot TyThings during the course of typechecking. We don't --- think (and have not observed) any cases where this would cause --- problems, but the hypothetical situation one might worry about --- is something along these lines in Core: --- --- case x of --- A -> e1 --- B -> e2 --- --- If, when typechecking this, we find x :: T, and the T we are hooked --- up with is the abstract one from the hs-boot file, rather than the --- one defined in this module with constructors A and B. But it's hard --- to see how this could happen, especially because the reference to --- the constructor (A and B) means that GHC will always typecheck --- this expression *after* typechecking T. + Succeeded thing -> return thing } tcIfaceTyCon :: IfaceTyCon -> IfL TyCon tcIfaceTyCon (IfaceTyCon name _info) ===================================== compiler/GHC/Rename/Env.hs ===================================== @@ -68,7 +68,11 @@ import GHC.Tc.Utils.Env import GHC.Tc.Types.LclEnv import GHC.Tc.Utils.Monad import GHC.Parser.PostProcess ( setRdrNameSpace ) + import GHC.Builtin.Types +import GHC.Builtin.Utils( knownKeyOccMap ) +import GHC.Builtin.Names( rOOT_MAIN ) + import GHC.Types.Name import GHC.Types.Name.Set import GHC.Types.Name.Env @@ -79,11 +83,11 @@ import GHC.Unit.Module.ModIface import GHC.Core.ConLike import GHC.Core.DataCon import GHC.Core.TyCon -import GHC.Builtin.Names( rOOT_MAIN ) import GHC.Types.Basic ( TupleSort(..), tupleSortBoxity ) import GHC.Types.TyThing ( tyThingGREInfo ) import GHC.Types.SrcLoc as SrcLoc import GHC.Utils.Outputable as Outputable +import GHC.Types.Unique import GHC.Types.Unique.FM import GHC.Types.Unique.DSet import GHC.Types.Unique.Set @@ -224,11 +228,11 @@ newTopSrcBinder (L loc rdr_name) -- the RdrName, not from the environment. In principle, it'd be fine to -- have an arbitrary mixture of external core definitions in a single module, -- (apart from module-initialisation issues, perhaps). - ; newGlobalBinder rdr_mod rdr_occ (locA loc) } + ; newGlobalBinder rdr_mod rdr_occ Nothing (locA loc) } | otherwise - = do { when (isQual rdr_name) - (addErrAt (locA loc) (badQualBndrErr rdr_name)) + = do { when (isQual rdr_name) $ + addErrAt (locA loc) (badQualBndrErr rdr_name) -- Binders should not be qualified; if they are, and with a different -- module name, we get a confusing "M.T is not in scope" error later @@ -239,11 +243,30 @@ newTopSrcBinder (L loc rdr_name) do { uniq <- newUnique ; return (mkInternalName uniq (rdrNameOcc rdr_name) (locA loc)) } else - do { this_mod <- getModule - ; traceRn "newTopSrcBinder" (ppr this_mod $$ ppr rdr_name $$ ppr (locA loc)) - ; newGlobalBinder this_mod (rdrNameOcc rdr_name) (locA loc) } + -- Finally we get the "normal path"; an ordinary, top-level binding + newTopVanillaSrcBinder (rdrNameOcc rdr_name) (locA loc) } +newTopVanillaSrcBinder :: OccName -> SrcSpan -> RnM Name +newTopVanillaSrcBinder occ loc + = do { this_mod <- getModule + + -- See if this bindings is for a known-key name, and if so get its Unique + ; defines_known_keys <- xoptM LangExt.DefinesKnownKeyNames + ; let mb_uniq :: Maybe Unique + mb_uniq | defines_known_keys = lookupOccEnv knownKeyOccMap occ + | otherwise = Nothing + + ; name <- newGlobalBinder this_mod occ mb_uniq loc + ; traceRn "newTopSrcBinder" $ + vcat [ text "module:" <+> ppr this_mod + , text "occ:" <+> ppr occ + , text "mb_uniq:" <+> ppr mb_uniq + , text "loc:" <+> ppr loc + , text "name:" <+> ppr name ] + ; return name + } + {- ********************************************************* * * ===================================== compiler/GHC/Tc/Deriv/Generics.hs ===================================== @@ -445,7 +445,7 @@ gen_Generic_fam_inst gk get_fixity loc ; mod <- getModule ; let tc_occ = nameOccName (tyConName tycon) rep_occ = case gk of Gen0 -> mkGenR tc_occ; Gen1 -> mkGen1R tc_occ - ; rep_name <- newGlobalBinder mod rep_occ loc + ; rep_name <- newGlobalBinder mod rep_occ Nothing loc ; let tcv = tyCoVarsOfTypeList inst_ty (tv, cv) = partition isTyVar tcv ===================================== compiler/GHC/Tc/Gen/Splice.hs ===================================== @@ -76,7 +76,6 @@ import GHC.ThToHs import GHC.HsToCore.Docs import GHC.HsToCore.Expr import GHC.HsToCore.Monad -import GHC.IfaceToCore import GHC.Iface.Load import GHCi.Message ===================================== compiler/GHC/Tc/Instance/Typeable.hs ===================================== @@ -188,7 +188,7 @@ mkModIdBindings :: TcM TcGblEnv mkModIdBindings = do { mod <- getModule ; loc <- getSrcSpanM - ; mod_nm <- newGlobalBinder mod (mkVarOccFS (fsLit "$trModule")) loc + ; mod_nm <- newGlobalBinder mod (mkVarOccFS (fsLit "$trModule")) Nothing loc ; trModuleTyCon <- tcLookupTyCon trModuleTyConName ; let mod_id = mkExportedVanillaId mod_nm (mkTyConApp trModuleTyCon []) ; mod_bind <- mkVarBind mod_id <$> mkModIdRHS mod ===================================== compiler/GHC/Tc/TyCl/Build.hs ===================================== @@ -429,7 +429,7 @@ newImplicitBinderLoc :: Name -- Base name -- Just the same, but lets you specify the SrcSpan newImplicitBinderLoc base_name mk_sys_occ loc | Just mod <- nameModule_maybe base_name - = newGlobalBinder mod occ loc + = newGlobalBinder mod occ Nothing loc | otherwise -- When typechecking a [d| decl bracket |], -- TH generates types, classes etc with Internal names, -- so we follow suit for the implicit binders @@ -443,6 +443,6 @@ newTyConRepName :: Name -> TcRnIf gbl lcl TyConRepName newTyConRepName tc_name | Just mod <- nameModule_maybe tc_name , (mod, occ) <- tyConRepModOcc mod (nameOccName tc_name) - = newGlobalBinder mod occ noSrcSpan + = newGlobalBinder mod occ Nothing noSrcSpan | otherwise = newImplicitBinder tc_name mkTyConRepOcc ===================================== compiler/GHC/Tc/Types.hs ===================================== @@ -355,10 +355,9 @@ data IfGblEnv -- We need the module name so we can test when it's appropriate -- to look in this env. -- See Note [Tying the knot] in GHC.IfaceToCore - if_rec_types :: (KnotVars (IfG TypeEnv)) + if_rec_types :: KnotVars (IfG TypeEnv) -- Allows a read effect, so it can be in a mutable -- variable; c.f. handling the external package type env - -- Nothing => interactive stuff, no loops possible } data IfLclEnv ===================================== compiler/GHC/Tc/Utils/Env.hs ===================================== @@ -24,6 +24,7 @@ module GHC.Tc.Utils.Env( tcLookupRecSelParent, tcLookupLocatedGlobalId, tcLookupLocatedTyCon, tcLookupLocatedClass, tcLookupAxiom, + tcLookupImported_maybe, lookupGlobal, lookupGlobal_maybe, addTypecheckedBinds, addEvBinds, addTopEvBinds, failIllegalTyCon, failIllegalTyVar, @@ -58,8 +59,8 @@ module GHC.Tc.Utils.Env( -- Template Haskell stuff LevelCheckReason(..), - tcMetaTy, thLevelIndex, - isBrackLevel, + tcMetaTy, tcMetaKnownKeyTy, + thLevelIndex, isBrackLevel, -- New Ids newDFunName, @@ -268,6 +269,26 @@ tcLookupGlobal name Failed msg -> failWithTc (TcRnInterfaceError msg) }}} +tcLookupImported_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing) +-- Returns (Failed err) if we can't find the interface file for the thing +tcLookupImported_maybe name + = do { hsc_env <- getTopEnv + ; mb_thing <- liftIO (lookupType hsc_env name) + ; case mb_thing of + Just thing -> return (Succeeded thing) + Nothing -> tcImportDecl_maybe name } + +tcImportDecl_maybe :: Name -> TcM (MaybeErr IfaceMessage TyThing) +-- Entry point for *source-code* uses of importDecl +tcImportDecl_maybe name + | Just thing <- wiredInNameTyThing_maybe name + = do { when (needWiredInHomeIface thing) + (initIfaceTcRn (loadWiredInHomeIface name)) + -- See Note [Loading instances for wired-in things] + ; return (Succeeded thing) } + | otherwise + = initIfaceTcRn (importDecl name) + -- Look up only in this module's global env't. Don't look in imports, etc. -- Panic if it's not there. tcLookupGlobalOnly :: Name -> TcM TyThing @@ -932,13 +953,25 @@ tcExtendRules lcl_rules thing_inside ************************************************************************ -} +tcMetaKnownKeyTy :: HasDebugCallStack => Unique -> TcM Type +tcMetaKnownKeyTy uniq + = do { normal_path <- xoptM LangExt.ImplicitKnownKeyNames + ; mb_rdr_env <- if normal_path + then return Nothing + else Just <$> getGlobalRdrEnv + ; mb_thing <- initIfaceTcRn (lookupKnownKeyThing mb_rdr_env uniq) + ; case mb_thing of + Succeeded (ATyCon tc) -> return (mkTyConTy tc) + Succeeded thing -> wrongThingErr WrongThingTyCon (AGlobal thing) (getName thing) + Failed msg -> failWithTc (TcRnInterfaceError msg) } + tcMetaTy :: Name -> TcM Type -- Given the name of a Template Haskell data type, -- return the type -- E.g. given the name "Expr" return the type "Expr" -tcMetaTy tc_name = do - t <- tcLookupTyCon tc_name - return (mkTyConTy t) +tcMetaTy tc_name + = do { t <- tcLookupTyCon tc_name + ; return (mkTyConTy t) } isBrackLevel :: ThLevel -> Bool isBrackLevel (Brack {}) = True @@ -1135,7 +1168,7 @@ newDFunName clas tys loc ; let info_string = occNameString (getOccName clas) ++ concatMap (occNameString . getDFunTyKey) tys ; dfun_occ <- chooseUniqueOccTc (mkDFunOcc info_string is_boot) - ; newGlobalBinder mod dfun_occ loc } + ; newGlobalBinder mod dfun_occ Nothing loc } newFamInstTyConName :: LocatedN Name -> [Type] -> TcM Name newFamInstTyConName (L loc name) tys = mk_fam_inst_name id (locA loc) name [tys] @@ -1150,7 +1183,7 @@ mk_fam_inst_name adaptOcc loc tc_name tyss ; let info_string = occNameString (getOccName tc_name) ++ intercalate "|" ty_strings ; occ <- chooseUniqueOccTc (mkInstTyTcOcc info_string) - ; newGlobalBinder mod (adaptOcc occ) loc } + ; newGlobalBinder mod (adaptOcc occ) Nothing loc } where ty_strings = map (concatMap (occNameString . getDFunTyKey)) tyss @@ -1262,8 +1295,8 @@ notFound name } wrongThingErr :: WrongThingSort -> TcTyThing -> Name -> TcM a -wrongThingErr expected thing name = - failWithTc (TcRnTyThingUsedWrong expected thing name) +wrongThingErr expected thing name + = failWithTc (TcRnTyThingUsedWrong expected thing name) {- Note [Out of scope might be a staging error] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ===================================== compiler/GHC/Tc/Utils/Instantiate.hs ===================================== @@ -796,7 +796,7 @@ mkOverLit (HsIntegral i) ; return (XLit $ HsInteger (il_text i) (il_value i) integer_ty) } mkOverLit (HsFractional r) - = do { rat_ty <- tcMetaTy rationalTyConName + = do { rat_ty <- tcMetaKnownKeyTy rationalTyConKey ; return (XLit $ HsRat r rat_ty) } mkOverLit (HsIsString src s) = return (HsString src s) ===================================== compiler/GHC/Tc/Utils/Monad.hs ===================================== @@ -2391,8 +2391,8 @@ initIfaceTcRn thing_inside -- bangs to avoid leaking the envs (#19356) ; let !mhome_unit = hsc_home_unit_maybe hsc_env !knot_vars = tcg_type_env_var tcg_env - -- When we are instantiating a signature, we DEFINITELY - -- do not want to knot tie. + -- When we are instantiating a signature, + -- we DEFINITELY do not want to knot tie. is_instantiate = fromMaybe False (isHomeUnitInstantiating <$> mhome_unit) ; let { if_env = IfGblEnv { if_doc = text "initIfaceTcRn", ===================================== compiler/GHC/Types/Name/Cache.hs ===================================== @@ -32,6 +32,7 @@ import GHC.Builtin.Utils import GHC.Utils.Outputable import GHC.Utils.Panic +import GHC.Utils.Misc( HasDebugCallStack ) import Control.Applicative import Control.Concurrent.MVar @@ -134,12 +135,12 @@ lookupOrigNameCache nc mod occ = lookup_infinite <|> lookup_normal occ_env <- lookupModuleEnv nc mod lookupOccEnv occ_env occ -extendOrigNameCache' :: OrigNameCache -> Name -> OrigNameCache +extendOrigNameCache' :: HasDebugCallStack => OrigNameCache -> Name -> OrigNameCache extendOrigNameCache' nc name = assertPpr (isExternalName name) (ppr name) $ extendOrigNameCache nc (nameModule name) (nameOccName name) name -extendOrigNameCache :: OrigNameCache -> Module -> OccName -> Name -> OrigNameCache +extendOrigNameCache :: HasDebugCallStack => OrigNameCache -> Module -> OccName -> Name -> OrigNameCache extendOrigNameCache nc mod occ name = extendModuleEnvWith combine nc mod (unitOccEnv occ name) where ===================================== compiler/GHC/Unit/External.hs ===================================== @@ -3,6 +3,7 @@ module GHC.Unit.External , initExternalUnitCache , eucEPS , ExternalPackageState (..) + , KnownKeyNameMap , initExternalPackageState , EpsStats(..) , addEpsInStats @@ -21,8 +22,6 @@ import GHC.Prelude import GHC.Unit import GHC.Unit.Module.ModIface -import GHC.Builtin.Utils( KnownKeyOccMap) - import GHC.Core.FamInstEnv import GHC.Core.InstEnv ( InstEnv, emptyInstEnv ) import GHC.Core.Opt.ConstantFold @@ -32,7 +31,10 @@ import GHC.Types.Annotations ( AnnEnv, emptyAnnEnv ) import GHC.Types.CompleteMatch import GHC.Types.DefaultEnv (DefaultEnv) import GHC.Types.TypeEnv +import GHC.Types.Name( Name ) +import GHC.Types.Unique( Unique ) import GHC.Types.Unique.DSet +import GHC.Types.Unique.FM( UniqFM ) import GHC.Linker.Types (Linkable) @@ -153,7 +155,7 @@ data ExternalPackageState -- See Note [Interface Files with Core Definitions] eps_iface_bytecode :: !(ModuleEnv (IO Linkable)), - eps_known_keys :: Maybe KnownKeyOccMap, -- ^ See Note [Overview of KnownKeyNames] + eps_known_keys :: Maybe KnownKeyNameMap, -- ^ See Note [Overview of KnownKeyNames] eps_inst_env :: !PackageInstEnv, -- ^ The total 'InstEnv' accumulated -- from all the external-package modules @@ -174,6 +176,8 @@ data ExternalPackageState eps_defaults :: !(ModuleEnv DefaultEnv) -- ^ Default declarations exported by external packages } +type KnownKeyNameMap = UniqFM Unique Name -- See Note [Overview of known-key Names] + -- | Accumulated statistics about what we are putting into the 'ExternalPackageState'. -- \"In\" means stuff that is just /read/ from interface files, -- \"Out\" means actually sucked in and type-checked ===================================== libraries/base/base.cabal.in ===================================== @@ -28,7 +28,7 @@ extra-doc-files: Library default-language: Haskell2010 - default-extensions: NoImplicitPrelude + default-extensions: NoImplicitPrelude, NoImplicitKnownKeyNames build-depends: ghc-internal == @ProjectVersionForLib@.*, ghc-prim, ===================================== libraries/ghc-internal/ghc-internal.cabal.in ===================================== @@ -81,6 +81,7 @@ Library default-language: Haskell2010 default-extensions: NoImplicitPrelude + NoImplicitKnownKeyNames other-extensions: BangPatterns CApiFFI ===================================== libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs ===================================== @@ -55,7 +55,8 @@ data Extension | QuasiQuotes | ImplicitParams | ImplicitPrelude - | ImplicitKnownKeyNames -- TODO: Note for knownkey names + | ImplicitKnownKeyNames -- See Note [Overview of known-key names] + | DefinesKnownKeyNames -- See Note [Overview of known-key names] | ScopedTypeVariables | AllowAmbiguousTypes | UnboxedTuples ===================================== libraries/ghc-internal/src/GHC/Internal/Real.hs ===================================== @@ -1,4 +1,5 @@ {-# LANGUAGE Trustworthy #-} +{-# LANGUAGE DefinesKnownKeyNames #-} {-# LANGUAGE CPP, NoImplicitPrelude, MagicHash, UnboxedTuples, BangPatterns #-} {-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_HADDOCK not-home #-} View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/88d760d98757119c048d701529ceb4ba... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/88d760d98757119c048d701529ceb4ba... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Simon Peyton Jones (@simonpj)