Simon Peyton Jones pushed to branch wip/spj-reinstallable-base2 at Glasgow Haskell Compiler / GHC
Commits:
-
2239f43c
by Simon Peyton Jones at 2026-04-15T12:03:41+01:00
8 changed files:
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/Monad.hs
Changes:
| ... | ... | @@ -178,16 +178,16 @@ configured via command-line flags (in `GHC.setTopSessionDynFlags`). |
| 178 | 178 | |
| 179 | 179 | -- Note [hsc_type_env_var hack]
|
| 180 | 180 | -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 181 | --- hsc_type_env_var is used to initialize tcg_type_env_var, and
|
|
| 181 | +-- hsc_type_env_var is used to initialize tcg_knot_vars, and
|
|
| 182 | 182 | -- eventually it is the mutable variable that is queried from
|
| 183 | 183 | -- if_rec_types to get a TypeEnv. So, clearly, it's something
|
| 184 | 184 | -- related to knot-tying (see Note [Tying the knot]).
|
| 185 | 185 | -- hsc_type_env_var is used in two places: initTcRn (where
|
| 186 | --- it initializes tcg_type_env_var) and initIfaceCheck
|
|
| 186 | +-- it initializes tcg_knot_vars) and initIfaceCheck
|
|
| 187 | 187 | -- (where it initializes if_rec_types).
|
| 188 | 188 | --
|
| 189 | 189 | -- But why do we need a way to feed a mutable variable in? Why
|
| 190 | --- can't we just initialize tcg_type_env_var when we start
|
|
| 190 | +-- can't we just initialize tcg_knot_vars when we start
|
|
| 191 | 191 | -- typechecking? The problem is we need to knot-tie the
|
| 192 | 192 | -- EPS, and we may start adding things to the EPS before type
|
| 193 | 193 | -- checking starts.
|
| ... | ... | @@ -83,8 +83,8 @@ data HscEnv |
| 83 | 83 | |
| 84 | 84 | hsc_type_env_vars :: KnotVars (IORef TypeEnv)
|
| 85 | 85 | -- ^ Used for one-shot compilation only, to initialise
|
| 86 | - -- the 'IfGblEnv'. See 'GHC.Tc.Utils.tcg_type_env_var' for
|
|
| 87 | - -- 'GHC.Tc.Utils.TcGblEnv'. See also Note [hsc_type_env_var hack]
|
|
| 86 | + -- the 'IfGblEnv'. See 'tcg_knot_vars' in 'GHC.Tc.Utils.TcGblEnv'.
|
|
| 87 | + -- See also Note [hsc_type_env_var hack]
|
|
| 88 | 88 | |
| 89 | 89 | , hsc_interp :: Maybe Interp
|
| 90 | 90 | -- ^ target code interpreter (if any) to use for TH and GHCi.
|
| ... | ... | @@ -731,7 +731,7 @@ runHscPhase pipe_env hsc_env0 input_fn src_flavour = do |
| 731 | 731 | mg <- downsweepThunk hsc_env mod_summary
|
| 732 | 732 | |
| 733 | 733 | -- Need to set the knot-tying mutable variable for interface
|
| 734 | - -- files. See GHC.Tc.Utils.TcGblEnv.tcg_type_env_var.
|
|
| 734 | + -- files. See GHC.Tc.Utils.TcGblEnv.tcg_knot_vars
|
|
| 735 | 735 | -- See also Note [hsc_type_env_var hack]
|
| 736 | 736 | type_env_var <- newIORef emptyNameEnv
|
| 737 | 737 | let hsc_env' =
|
| ... | ... | @@ -332,13 +332,17 @@ tcRnModuleTcRnM hsc_env mod_sum |
| 332 | 332 | ; whenM (goptM Opt_DoCoreLinting) $
|
| 333 | 333 | lintGblEnv (hsc_logger hsc_env) (hsc_dflags hsc_env) tcg_env
|
| 334 | 334 | |
| 335 | + -- Sync the knot-tied type environment before checking
|
|
| 336 | + -- the M.hi-boot interface, if any
|
|
| 337 | + ; syncTypeEnvKnotVars tcg_env
|
|
| 338 | + |
|
| 335 | 339 | ; setGblEnv tcg_env
|
| 336 | 340 | $ do { -- Compare hi-boot iface (if any) with the real thing
|
| 337 | 341 | -- Must be done after processing the exports
|
| 338 | 342 | tcg_env <- checkHiBootIface tcg_env boot_info
|
| 339 | 343 | ; -- The new type env is already available to stuff
|
| 340 | - -- slurped from interface files, via
|
|
| 341 | - -- GHC.Tc.Utils.Env.setGlobalTypeEnv. It's important that this
|
|
| 344 | + -- slurped from interface files, via syncTypeEnvKnotVars,
|
|
| 345 | + -- itself called by tcRnSrcDecls. It's important that this
|
|
| 342 | 346 | -- includes the stuff in checkHiBootIface,
|
| 343 | 347 | -- because the latter might add new bindings for
|
| 344 | 348 | -- boot_dfuns, which may be mentioned in imported
|
| ... | ... | @@ -570,6 +574,11 @@ tcRnSrcDecls explicit_mod_hdr export_ies decls |
| 570 | 574 | ; ev_binds <- simplifyTop (lie `andWC` lie_main)
|
| 571 | 575 | ; return (tcg_env `addEvBinds` ev_binds) }
|
| 572 | 576 | |
| 577 | + -- Update the knot-tied type environment to include everything
|
|
| 578 | + -- bound in this module. Do this now because when compiling GHC.Internal.Types,
|
|
| 579 | + -- mkTypeableBinds needs to "see" the definition of `Module`
|
|
| 580 | + ; syncTypeEnvKnotVars tcg_env
|
|
| 581 | + |
|
| 573 | 582 | -- Emit Typeable bindings
|
| 574 | 583 | ; tcg_env <- setGblEnv tcg_env $
|
| 575 | 584 | mkTypeableBinds
|
| ... | ... | @@ -643,15 +652,15 @@ tcRnSrcDecls explicit_mod_hdr export_ies decls |
| 643 | 652 | -- to the previous tcg_env
|
| 644 | 653 | |
| 645 | 654 | ; tcg_env' = tcg_env
|
| 646 | - { tcg_binds = binds' ++ binds_mf
|
|
| 655 | + { tcg_type_env = final_type_env
|
|
| 656 | + , tcg_binds = binds' ++ binds_mf
|
|
| 647 | 657 | , tcg_ev_binds = ev_binds' `unionBags` ev_binds_mf
|
| 648 | 658 | , tcg_imp_specs = imp_specs' ++ imp_specs_mf
|
| 649 | 659 | , tcg_rules = rules' ++ rules_mf
|
| 650 | 660 | , tcg_fords = fords' ++ fords_mf
|
| 651 | 661 | , tcg_patsyns = pat_syns' ++ patsyns_mf } } ;
|
| 652 | 662 | |
| 653 | - ; setGlobalTypeEnv tcg_env' final_type_env
|
|
| 654 | - }
|
|
| 663 | + ; return tcg_env' }
|
|
| 655 | 664 | |
| 656 | 665 | zonkTcGblEnv :: TcGblEnv
|
| 657 | 666 | -> TcM (TypeEnv, Bag EvBind, LHsBinds GhcTc,
|
| ... | ... | @@ -834,10 +843,11 @@ tcRnHsBootDecls boot_or_sig decls |
| 834 | 843 | ; let { type_env0 = tcg_type_env gbl_env
|
| 835 | 844 | ; type_env1 = extendTypeEnvWithIds type_env0 val_ids
|
| 836 | 845 | ; type_env2 = extendTypeEnvWithIds type_env1 dfun_ids
|
| 837 | - ; dfun_ids = map iDFunId inst_infos
|
|
| 846 | + ; dfun_ids = map iDFunId inst_infos
|
|
| 847 | + ; gbl_env' = gbl_env { tcg_type_env = type_env2 }
|
|
| 838 | 848 | }
|
| 839 | 849 | |
| 840 | - ; setGlobalTypeEnv gbl_env type_env2
|
|
| 850 | + ; return gbl_env'
|
|
| 841 | 851 | }}}
|
| 842 | 852 | ; traceTc "boot" (ppr lie); return gbl_env }
|
| 843 | 853 | |
| ... | ... | @@ -875,20 +885,14 @@ checkHiBootIface tcg_env boot_info |
| 875 | 885 | --
|
| 876 | 886 | -- to (a) the type envt, and (b) the top-level bindings
|
| 877 | 887 | ; let boot_impedance_bds = map fst imp_prs
|
| 878 | - type_env' = extendTypeEnvWithIds local_type_env boot_impedance_bds
|
|
| 888 | + !type_env' = extendTypeEnvWithIds local_type_env boot_impedance_bds
|
|
| 879 | 889 | impedance_binds = [ mkVarBind boot_id (nlHsVar id)
|
| 880 | 890 | | (boot_id, id) <- imp_prs ]
|
| 881 | 891 | tcg_env_w_binds
|
| 882 | - = tcg_env { tcg_binds = binds ++ impedance_binds }
|
|
| 892 | + = tcg_env { tcg_type_env = type_env'
|
|
| 893 | + , tcg_binds = binds ++ impedance_binds }
|
|
| 883 | 894 | |
| 884 | - ; type_env' `seq`
|
|
| 885 | - -- Why the seq? Without, we will put a TypeEnv thunk in
|
|
| 886 | - -- tcg_type_env_var. That thunk will eventually get
|
|
| 887 | - -- forced if we are typechecking interfaces, but that
|
|
| 888 | - -- is no good if we are trying to typecheck the very
|
|
| 889 | - -- DFun we were going to put in.
|
|
| 890 | - -- TODO: Maybe setGlobalTypeEnv should be strict.
|
|
| 891 | - setGlobalTypeEnv tcg_env_w_binds type_env' }
|
|
| 895 | + ; return tcg_env_w_binds }
|
|
| 892 | 896 | |
| 893 | 897 | {- Note [DFun impedance matching]
|
| 894 | 898 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -978,7 +982,7 @@ This most works well, but there is one problem: DFuns! We do not want |
| 978 | 982 | to look at the mb_insts of the ModDetails in SelfBootInfo, because a
|
| 979 | 983 | dfun in one of those ClsInsts is gotten (in GHC.IfaceToCore.tcIfaceInst) by a
|
| 980 | 984 | (lazily evaluated) lookup in the if_rec_types. We could extend the
|
| 981 | -type env, do a setGloblaTypeEnv etc; but that all seems very indirect.
|
|
| 985 | +type env, do a syncTypeEnvKnotVars etc; but that all seems very indirect.
|
|
| 982 | 986 | It is much more directly simply to extract the DFunIds from the
|
| 983 | 987 | md_types of the SelfBootInfo.
|
| 984 | 988 |
| ... | ... | @@ -487,7 +487,7 @@ data TcGblEnv |
| 487 | 487 | -- NB: for what "things in this module" means, see
|
| 488 | 488 | -- Note [The interactive package] in "GHC.Runtime.Context"
|
| 489 | 489 | |
| 490 | - tcg_type_env_var :: KnotVars (IORef TypeEnv),
|
|
| 490 | + tcg_knot_vars :: KnotVars (IORef TypeEnv),
|
|
| 491 | 491 | -- Used only to initialise the interface-file
|
| 492 | 492 | -- typechecker in initIfaceTcRn, so that it can see stuff
|
| 493 | 493 | -- bound in this module when dealing with hi-boot recursions
|
| ... | ... | @@ -739,7 +739,7 @@ mergeSignatures |
| 739 | 739 | , rdr_elt <- lookupGRE rdr_env (LookupOccName occ AllRelevantGREs) ]
|
| 740 | 740 | |
| 741 | 741 | -- STEP 5: Typecheck the interfaces
|
| 742 | - let type_env_var = tcg_type_env_var tcg_env
|
|
| 742 | + let knot_type_env = tcg_knot_vars tcg_env
|
|
| 743 | 743 | |
| 744 | 744 | -- typecheckIfacesForMerging does two things:
|
| 745 | 745 | -- 1. It merges the all of the ifaces together, and typechecks the
|
| ... | ... | @@ -748,7 +748,7 @@ mergeSignatures |
| 748 | 748 | -- resolving to the merged type_env from (1).
|
| 749 | 749 | -- See typecheckIfacesForMerging for more details.
|
| 750 | 750 | (type_env, detailss) <- initIfaceTcRn $
|
| 751 | - typecheckIfacesForMerging inner_mod ifaces type_env_var
|
|
| 751 | + typecheckIfacesForMerging inner_mod ifaces knot_type_env
|
|
| 752 | 752 | let infos = zip ifaces detailss
|
| 753 | 753 | |
| 754 | 754 | -- Test for cycles
|
| ... | ... | @@ -764,7 +764,7 @@ mergeSignatures |
| 764 | 764 | -- NB: Why do we set tcg_tcs/tcg_patsyns/tcg_type_env directly,
|
| 765 | 765 | -- rather than use tcExtendGlobalEnv (the normal method to add newly
|
| 766 | 766 | -- defined types to TcGblEnv?) tcExtendGlobalEnv adds these
|
| 767 | - -- TyThings to 'tcg_type_env_var', which is consulted when
|
|
| 767 | + -- TyThings to 'tcg_knot_vars', which is consulted when
|
|
| 768 | 768 | -- we read in interfaces to tie the knot. But *these TyThings themselves
|
| 769 | 769 | -- come from interface*, so that would result in deadlock. Don't
|
| 770 | 770 | -- update it!
|
| ... | ... | @@ -16,7 +16,7 @@ module GHC.Tc.Utils.Env( |
| 16 | 16 | |
| 17 | 17 | -- Global environment
|
| 18 | 18 | tcExtendGlobalEnv, tcExtendTyConEnv,
|
| 19 | - tcExtendGlobalEnvImplicit, setGlobalTypeEnv,
|
|
| 19 | + tcExtendGlobalEnvImplicit, syncTypeEnvKnotVars,
|
|
| 20 | 20 | tcExtendGlobalValEnv, tcTyThBinders,
|
| 21 | 21 | tcLookupLocatedGlobal, tcLookupGlobal, tcLookupGlobalOnly,
|
| 22 | 22 | tcLookupTyCon, tcLookupClass,
|
| ... | ... | @@ -606,16 +606,21 @@ get_id do_the_lookup |
| 606 | 606 | ************************************************************************
|
| 607 | 607 | -}
|
| 608 | 608 | |
| 609 | -setGlobalTypeEnv :: TcGblEnv -> TypeEnv -> TcM TcGblEnv
|
|
| 610 | --- Use this to update the global type env
|
|
| 611 | --- It updates both * the normal tcg_type_env field
|
|
| 612 | --- * the tcg_type_env_var field seen by interface files
|
|
| 613 | -setGlobalTypeEnv tcg_env new_type_env
|
|
| 614 | - = do { -- Sync the type-envt variable seen by interface files
|
|
| 615 | - ; case lookupKnotVars (tcg_type_env_var tcg_env) (tcg_mod tcg_env) of
|
|
| 616 | - Just tcg_env_var -> writeMutVar tcg_env_var new_type_env
|
|
| 617 | - Nothing -> return ()
|
|
| 618 | - ; return (tcg_env { tcg_type_env = new_type_env }) }
|
|
| 609 | +syncTypeEnvKnotVars :: TcGblEnv -> TcM ()
|
|
| 610 | +-- Use this to sync the tcg_knot_vars with the current type env
|
|
| 611 | +-- so that interface-file and known-key/occ lookups will find the
|
|
| 612 | +-- current bindings
|
|
| 613 | +--
|
|
| 614 | +-- Why the "!" before writing it into the variable? Without, we will put
|
|
| 615 | +-- a TypeEnv thunk into the knot-tied variable. That thunk will eventually get
|
|
| 616 | +-- forced if we are typechecking interfaces, but that is no good if we are
|
|
| 617 | +-- trying to typecheck the very DFun we were going to put in.
|
|
| 618 | +syncTypeEnvKnotVars tcg_env
|
|
| 619 | + = case lookupKnotVars (tcg_knot_vars tcg_env) (tcg_mod tcg_env) of
|
|
| 620 | + Just tcg_env_var -> do { let !type_env = tcg_type_env tcg_env
|
|
| 621 | + -- Why the "!"? See comment on the function
|
|
| 622 | + ; writeMutVar tcg_env_var type_env }
|
|
| 623 | + Nothing -> return ()
|
|
| 619 | 624 | |
| 620 | 625 | |
| 621 | 626 | tcExtendGlobalEnvImplicit :: [TyThing] -> TcM r -> TcM r
|
| ... | ... | @@ -623,8 +628,9 @@ tcExtendGlobalEnvImplicit :: [TyThing] -> TcM r -> TcM r |
| 623 | 628 | -- Do not extend tcg_tcs, tcg_patsyns etc
|
| 624 | 629 | tcExtendGlobalEnvImplicit things thing_inside
|
| 625 | 630 | = do { tcg_env <- getGblEnv
|
| 626 | - ; let ge' = extendTypeEnvList (tcg_type_env tcg_env) things
|
|
| 627 | - ; tcg_env' <- setGlobalTypeEnv tcg_env ge'
|
|
| 631 | + ; let !type_env' = extendTypeEnvList (tcg_type_env tcg_env) things
|
|
| 632 | + tcg_env' = tcg_env { tcg_type_env = type_env' }
|
|
| 633 | + ; syncTypeEnvKnotVars tcg_env'
|
|
| 628 | 634 | ; setGblEnv tcg_env' thing_inside }
|
| 629 | 635 | |
| 630 | 636 | tcExtendGlobalEnv :: [TyThing] -> TcM r -> TcM r
|
| ... | ... | @@ -677,8 +683,8 @@ tcExtendRecEnv gbl_stuff thing_inside |
| 677 | 683 | = do { tcg_env <- getGblEnv
|
| 678 | 684 | ; let ge' = extendNameEnvList (tcg_type_env tcg_env) gbl_stuff
|
| 679 | 685 | tcg_env' = tcg_env { tcg_type_env = ge' }
|
| 680 | - -- No need for setGlobalTypeEnv (which side-effects the
|
|
| 681 | - -- tcg_type_env_var); tcExtendRecEnv is used just
|
|
| 686 | + -- No need for syncTypeEnvKnotVars (which side-effects the
|
|
| 687 | + -- tcg_knot_vars); tcExtendRecEnv is used just
|
|
| 682 | 688 | -- when kind-check a group of type/class decls. It would
|
| 683 | 689 | -- in any case be wrong for an interface-file decl to end up
|
| 684 | 690 | -- with a TcTyCon in it!
|
| ... | ... | @@ -353,7 +353,7 @@ initTcGblEnv hsc_env hsc_src keep_rn_syntax mod loc = |
| 353 | 353 | , tcg_default = emptyDefaultEnv
|
| 354 | 354 | , tcg_default_exports = emptyDefaultEnv
|
| 355 | 355 | , tcg_type_env = emptyNameEnv
|
| 356 | - , tcg_type_env_var = hsc_type_env_vars hsc_env
|
|
| 356 | + , tcg_knot_vars = hsc_type_env_vars hsc_env
|
|
| 357 | 357 | , tcg_inst_env = emptyInstEnv
|
| 358 | 358 | , tcg_fam_inst_env = emptyFamInstEnv
|
| 359 | 359 | , tcg_ann_env = emptyAnnEnv
|
| ... | ... | @@ -2404,7 +2404,7 @@ initIfaceTcRn thing_inside |
| 2404 | 2404 | ; hsc_env <- getTopEnv
|
| 2405 | 2405 | -- bangs to avoid leaking the envs (#19356)
|
| 2406 | 2406 | ; let !mhome_unit = hsc_home_unit_maybe hsc_env
|
| 2407 | - !knot_vars = tcg_type_env_var tcg_env
|
|
| 2407 | + !knot_vars = tcg_knot_vars tcg_env
|
|
| 2408 | 2408 | -- When we are instantiating a signature,
|
| 2409 | 2409 | -- we DEFINITELY do not want to knot tie.
|
| 2410 | 2410 | is_instantiate = fromMaybe False (isHomeUnitInstantiating <$> mhome_unit)
|