
Apoorv Ingle pushed to branch wip/spj-apporv-Oct24 at Glasgow Haskell Compiler / GHC Commits: 5f213bff by fendor at 2025-06-02T09:16:24+02:00 Make GHCi commands compatible with multiple home units === Design We enable all GHCi features that were previously guarded by the `inMulti` option. GHCi supported multiple home units up to a certain degree for quite a while now. The supported feature set was limited, due to a design impasse: One of the home units must be "active", e.g., there must be one `HomeUnit` whose `UnitId` is "active" which is returned when calling ```haskell do hscActiveUnitId <$> getSession ``` This makes sense in a GHC session, since you are always compiling a particular Module, but it makes less intuitive sense in an interactive session. Given an expression to evaluate, we can't easily tell in which "context" the expression should be parsed, typechecked and evaluated. That's why initially, most of GHCi features, except for `:reload`ing were disabled if the GHCi session had more than one `HomeUnitEnv`. We lift this restriction, enabling all features of GHCi for the multiple home unit case. To do this, we fundamentally change the `HomeUnitEnv` graph to be multiple home unit first. Instead of differentiating the case were we have a single home unit and multiple, we now always set up a multiple home unit session that scales seamlessly to an arbitrary amount of home units. We introduce two new `HomeUnitEnv`s that are always added to the `HomeUnitGraph`. They are: The "interactive-ghci", called the `interactiveGhciUnit`, contains the same `DynFlags` that are used by the `InteractiveContext` for interactive evaluation of expressions. This `HomeUnitEnv` is only used on the prompt of GHCi, so we may refer to it as "interactive-prompt" unit. See Note [Relation between the `InteractiveContext` and `interactiveGhciUnitId`] for discussing its role. And the "interactive-session"", called `interactiveSessionUnit` or `interactiveSessionUnitId`, which is used for loading Scripts into GHCi that are not `Target`s of any home unit, via `:load` or `:add`. Both of these "interactive" home units depend on all other `HomeUnitEnv`s that are passed as arguments on the cli. Additionally, the "interactive-ghci" unit depends on `interactive-session`. We always evaluate expressions in the context of the "interactive-ghci" session. Since "interactive-ghci" depends on all home units, we can import any `Module` from the other home units with ease. As we have a clear `HomeUnitGraph` hierarchy, we can set `interactiveGhciUnitId` as the active home unit for the full duration of the GHCi session. In GHCi, we always set `interactiveGhciUnitId` to be the currently active home unit. === Implementation Details Given this design idea, the implementation is relatively straight forward. The core insight is that a `ModuleName` is not sufficient to identify a `Module` in the `HomeUnitGraph`. Thus, large parts of the PR is simply about refactoring usages of `ModuleName` to prefer `Module`, which has a `Unit` attached and is unique over the `HomeUnitGraph`. Consequentially, most usages of `lookupHPT` are likely to be incorrect and have been replaced by `lookupHugByModule` which is keyed by a `Module`. In `GHCi/UI.hs`, we make sure there is only one location where we are actually translating `ModuleName` to a `Module`: * `lookupQualifiedModuleName` If a `ModuleName` is ambiguous, we detect this and report it to the user. To avoid repeated lookups of `ModuleName`s, we store the `Module` in the `InteractiveImport`, which additionally simplifies the interface loading. A subtle detail is that the `DynFlags` of the `InteractiveContext` are now stored both in the `HomeUnitGraph` and in the `InteractiveContext`. In UI.hs, there are multiple code paths where we are careful to update the `DynFlags` in both locations. Most importantly in `addToProgramDynFlags`. --- There is one metric increase in this commit: ------------------------- Metric Increase: T4029 ------------------------- It is an increase from 14.4 MB to 16.1 MB (+11.8%) which sounds like a pretty big regression at first. However, we argue this increase is solely caused by using more data structures for managing multiple home units in the GHCi session. In particular, due to the design decision of using three home units, the base memory usage increases... but by how much? A big contributor is the `UnitState`, of which we have three now, which on its own 260 KB per instance. That makes an additional memory usage of 520 KB, already explaining a third of the overall memory usage increase. Then we store more elements in the `HomeUnitGraph`, we have more `HomeUnitEnv` entries, etc... While we didn't chase down each byte, we looked at the memory usage over time for both `-hi` and `-hT` profiles and can say with confidence while the memory usage increased slightly, we did not introduce any space leak, as the graph looks almost identical as the memory usage graph of GHC HEAD. --- Adds testcases for GHCi multiple home units session * Test truly multiple home unit sessions, testing reload logic and code evaluation. * Test that GHCi commands such as `:all-types`, `:browse`, etc., work * Object code reloading for home modules * GHCi debugger multiple home units session - - - - - de603d01 by fendor at 2025-06-02T09:16:24+02:00 Update "loading compiled code" GHCi documentation To use object code in GHCi, the module needs to be compiled for use in GHCi. To do that, users need to compile their modules with: * `-dynamic` * `-this-unit-id interactive-session` Otherwise, the interface files will not match. - - - - - b255a8ca by Vladislav Zavialov at 2025-06-02T16:00:12-04:00 docs: Fix code example for NoListTuplePuns Without the fix, the example produces an error: Test.hs:11:3: error: [GHC-45219] • Data constructor ‘Tuple’ returns type ‘Tuple2 a b’ instead of an instance of its parent type ‘Tuple a’ • In the definition of data constructor ‘Tuple’ In the data type declaration for ‘Tuple’ Fortunately, a one line change makes it compile. - - - - - 9f51d952 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 - Remove one `SrcSpan` field from `VAExpansion`. It is no longer needed. - Make `tcExpr` take a `Maybe HsThingRn` which will be passed on to tcApp and used by splitHsApps to determine a more accurate `AppCtx` - `tcXExpr` is less hacky now - do not look through HsExpansion applications - kill OrigPat and remove HsThingRn From VAExpansion - look through XExpr ExpandedThingRn while inferring type of head - always set in generated code after stepping inside a ExpandedThingRn - fixing record update error messages - remove special case of tcbody from tcLambdaMatches - wrap last stmt expansion in a HsPar so that the error messages are prettier - remove special case of dsExpr for ExpandedThingTc - make EExpand (HsExpr GhcRn) instead of EExpand HsThingRn - fixing error messages for rebindable - - - - - 86251b13 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 some progress on tick - - - - - 2fd9e8ce by Apoorv Ingle at 2025-06-05T17:15:45-05:00 remove adhoc cases from ticks - - - - - 11f767e6 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 fix the case where head of the application chain is an expanded expression and the argument is a type application c.f. T19167.hs - - - - - c9e2bdd1 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 move setQLInstLevel inside tcInstFun - - - - - becc473a by Apoorv Ingle at 2025-06-05T17:15:45-05:00 ignore ds warnings originating from gen locations - - - - - e88f1687 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 filter expr stmts error msgs - - - - - cfd7e10a by Apoorv Ingle at 2025-06-05T17:15:45-05:00 exception for AppDo while making error ctxt - - - - - b2195635 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 moving around things for locations and error ctxts - - - - - 2823806b by Apoorv Ingle at 2025-06-05T17:15:45-05:00 popErrCtxt doesn't push contexts and popErrCtxts in the first argument to bind and >> in do expansion statements - - - - - f3b6eb3c by Apoorv Ingle at 2025-06-05T17:15:45-05:00 accept test cases with changed error messages ------------------------- Metric Decrease: T9020 ------------------------- - - - - - 6d259023 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 look through PopErrCtxt while splitting exprs in application chains - - - - - 43db9ee8 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 remove special case for HsExpanded in Ticks - - - - - 743ad9d5 by Apoorv Ingle at 2025-06-05T17:15:45-05:00 check the right origin for record selector incomplete warnings - - - - - cd6c239c by Apoorv Ingle at 2025-06-05T17:15:45-05:00 kill VAExpansion - - - - - 800ac3cd by Apoorv Ingle at 2025-06-05T17:15:46-05:00 pass CtOrigin to tcApp for instantiateSigma - - - - - 169edd9c by Apoorv Ingle at 2025-06-05T17:15:46-05:00 do not suppress pprArising - - - - - 172 changed files: - compiler/GHC.hs - compiler/GHC/Driver/Downsweep.hs - compiler/GHC/Driver/Session.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/HsToCore/Expr.hs - compiler/GHC/HsToCore/Match.hs - compiler/GHC/HsToCore/Pmc.hs - compiler/GHC/HsToCore/Quote.hs - compiler/GHC/HsToCore/Ticks.hs - compiler/GHC/Iface/Load.hs - compiler/GHC/Rename/Expr.hs - compiler/GHC/Rename/Unbound.hs - compiler/GHC/Runtime/Context.hs - compiler/GHC/Runtime/Eval.hs - compiler/GHC/StgToByteCode.hs - compiler/GHC/StgToJS/Linker/Linker.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Gen/App.hs - + compiler/GHC/Tc/Gen/App.hs-boot - compiler/GHC/Tc/Gen/Do.hs - compiler/GHC/Tc/Gen/Expr.hs - compiler/GHC/Tc/Gen/Head.hs - compiler/GHC/Tc/Gen/Match.hs - compiler/GHC/Tc/Instance/Class.hs - compiler/GHC/Tc/Module.hs - compiler/GHC/Tc/Types/Origin.hs - compiler/GHC/Tc/Utils/Monad.hs - compiler/GHC/Types/Name/Ppr.hs - compiler/GHC/Unit/Env.hs - compiler/GHC/Unit/Home/Graph.hs - compiler/GHC/Unit/Types.hs - docs/users_guide/exts/data_kinds.rst - docs/users_guide/ghci.rst - ghc/GHCi/UI.hs - ghc/GHCi/UI/Exception.hs - ghc/GHCi/UI/Info.hs - ghc/GHCi/UI/Monad.hs - ghc/Main.hs - testsuite/driver/testlib.py - testsuite/tests/deSugar/should_compile/T10662.stderr - testsuite/tests/deSugar/should_compile/T3263-1.stderr - testsuite/tests/deSugar/should_compile/T3263-2.stderr - testsuite/tests/default/default-fail05.stderr - testsuite/tests/driver/T8526/T8526.stdout - testsuite/tests/driver/fat-iface/fat014.stdout - testsuite/tests/driver/multipleHomeUnits/multiGHCi.stderr - testsuite/tests/ghc-api/T6145.hs - testsuite/tests/ghc-api/annotations-literals/literals.hs - testsuite/tests/ghc-api/annotations-literals/parsed.hs - testsuite/tests/ghc-api/apirecomp001/myghc.hs - testsuite/tests/ghc-api/fixed-nodes/T1.hs - + testsuite/tests/ghci.debugger/scripts/break031/Makefile - + testsuite/tests/ghci.debugger/scripts/break031/a/A.hs - + testsuite/tests/ghci.debugger/scripts/break031/all.T - + testsuite/tests/ghci.debugger/scripts/break031/b/B.hs - + testsuite/tests/ghci.debugger/scripts/break031/break031a.script - + testsuite/tests/ghci.debugger/scripts/break031/break031a.stdout - + testsuite/tests/ghci.debugger/scripts/break031/break031b.script - + testsuite/tests/ghci.debugger/scripts/break031/break031b.stderr - + testsuite/tests/ghci.debugger/scripts/break031/break031b.stdout - + testsuite/tests/ghci.debugger/scripts/break031/unitA - + testsuite/tests/ghci.debugger/scripts/break031/unitB - testsuite/tests/ghci/linking/dyn/T3372.hs - + testsuite/tests/ghci/prog-mhu001/Makefile - + testsuite/tests/ghci/prog-mhu001/all.T - + testsuite/tests/ghci/prog-mhu001/e/E.hs - + testsuite/tests/ghci/prog-mhu001/prog-mhu001a.script - + testsuite/tests/ghci/prog-mhu001/prog-mhu001a.stdout - + testsuite/tests/ghci/prog-mhu001/prog-mhu001b.script - + testsuite/tests/ghci/prog-mhu001/prog-mhu001b.stdout - + testsuite/tests/ghci/prog-mhu001/prog-mhu001c.script - + testsuite/tests/ghci/prog-mhu001/prog-mhu001c.stdout - + testsuite/tests/ghci/prog-mhu001/prog-mhu001d.script - + testsuite/tests/ghci/prog-mhu001/prog-mhu001d.stdout - + testsuite/tests/ghci/prog-mhu001/prog-mhu001e.script - + testsuite/tests/ghci/prog-mhu001/prog-mhu001e.stdout - + testsuite/tests/ghci/prog-mhu001/prog-mhu001f.script - + testsuite/tests/ghci/prog-mhu001/prog-mhu001f.stdout - + testsuite/tests/ghci/prog-mhu001/unitE - + testsuite/tests/ghci/prog-mhu001/unitE-main-is - + testsuite/tests/ghci/prog-mhu002/Makefile - + testsuite/tests/ghci/prog-mhu002/a/A.hs - + testsuite/tests/ghci/prog-mhu002/all.T - + testsuite/tests/ghci/prog-mhu002/b/B.hs - + testsuite/tests/ghci/prog-mhu002/c/C.hs - + testsuite/tests/ghci/prog-mhu002/d/Main.hs - + testsuite/tests/ghci/prog-mhu002/prog-mhu002a.script - + testsuite/tests/ghci/prog-mhu002/prog-mhu002a.stderr - + testsuite/tests/ghci/prog-mhu002/prog-mhu002a.stdout - + testsuite/tests/ghci/prog-mhu002/prog-mhu002b.script - + testsuite/tests/ghci/prog-mhu002/prog-mhu002b.stderr - + testsuite/tests/ghci/prog-mhu002/prog-mhu002b.stdout - + testsuite/tests/ghci/prog-mhu002/prog-mhu002c.script - + testsuite/tests/ghci/prog-mhu002/prog-mhu002c.stdout - + testsuite/tests/ghci/prog-mhu002/prog-mhu002d.script - + testsuite/tests/ghci/prog-mhu002/prog-mhu002d.stdout - + testsuite/tests/ghci/prog-mhu002/prog-mhu002e.script - + testsuite/tests/ghci/prog-mhu002/prog-mhu002e.stdout - + testsuite/tests/ghci/prog-mhu002/prog-mhu002f.script - + testsuite/tests/ghci/prog-mhu002/prog-mhu002f.stdout - + testsuite/tests/ghci/prog-mhu002/unitA - + testsuite/tests/ghci/prog-mhu002/unitB - + testsuite/tests/ghci/prog-mhu002/unitC - + testsuite/tests/ghci/prog-mhu002/unitD - + testsuite/tests/ghci/prog-mhu003/Makefile - + testsuite/tests/ghci/prog-mhu003/a/A.hs - + testsuite/tests/ghci/prog-mhu003/all.T - + testsuite/tests/ghci/prog-mhu003/b/Foo.hs - + testsuite/tests/ghci/prog-mhu003/c/C.hs - + testsuite/tests/ghci/prog-mhu003/d/Foo.hs - + testsuite/tests/ghci/prog-mhu003/prog-mhu003.script - + testsuite/tests/ghci/prog-mhu003/prog-mhu003.stderr - + testsuite/tests/ghci/prog-mhu003/prog-mhu003.stdout - + testsuite/tests/ghci/prog-mhu003/unitA - + testsuite/tests/ghci/prog-mhu003/unitB - + testsuite/tests/ghci/prog-mhu003/unitC - + testsuite/tests/ghci/prog-mhu003/unitD - + testsuite/tests/ghci/prog-mhu004/Makefile - + testsuite/tests/ghci/prog-mhu004/a/Foo.hs - + testsuite/tests/ghci/prog-mhu004/all.T - + testsuite/tests/ghci/prog-mhu004/b/Foo.hs - + testsuite/tests/ghci/prog-mhu004/prog-mhu004a.script - + testsuite/tests/ghci/prog-mhu004/prog-mhu004a.stderr - + testsuite/tests/ghci/prog-mhu004/prog-mhu004a.stdout - + testsuite/tests/ghci/prog-mhu004/prog-mhu004b.script - + testsuite/tests/ghci/prog-mhu004/prog-mhu004b.stdout - + testsuite/tests/ghci/prog-mhu004/unitA - + testsuite/tests/ghci/prog-mhu004/unitB - testsuite/tests/ghci/prog010/ghci.prog010.script - testsuite/tests/ghci/prog018/prog018.stdout - + testsuite/tests/ghci/prog020/A.hs - + testsuite/tests/ghci/prog020/B.hs - + testsuite/tests/ghci/prog020/Makefile - + testsuite/tests/ghci/prog020/all.T - + testsuite/tests/ghci/prog020/ghci.prog020.script - + testsuite/tests/ghci/prog020/ghci.prog020.stderr - + testsuite/tests/ghci/prog020/ghci.prog020.stdout - testsuite/tests/ghci/scripts/T13869.stdout - testsuite/tests/ghci/scripts/T13997.stdout - testsuite/tests/ghci/scripts/T17669.stdout - testsuite/tests/ghci/scripts/T18330.stdout - testsuite/tests/ghci/scripts/T1914.stdout - testsuite/tests/ghci/scripts/T20217.stdout - testsuite/tests/ghci/scripts/T20587.stdout - testsuite/tests/ghci/scripts/T21110.stderr - testsuite/tests/ghci/scripts/T6105.stdout - testsuite/tests/ghci/scripts/T8042.stdout - testsuite/tests/ghci/scripts/T8042recomp.stdout - testsuite/tests/ghci/scripts/ghci024.stdout - testsuite/tests/ghci/scripts/ghci024.stdout-mingw32 - testsuite/tests/ghci/scripts/ghci058.script - testsuite/tests/ghci/should_run/TopEnvIface.stdout - testsuite/tests/indexed-types/should_fail/T2693.stderr - testsuite/tests/indexed-types/should_fail/T5439.stderr - testsuite/tests/plugins/test-defaulting-plugin.stderr - testsuite/tests/polykinds/T13393.stderr - testsuite/tests/printer/T17697.stderr - testsuite/tests/quasiquotation/T7918.hs - testsuite/tests/typecheck/should_compile/T14590.stderr - testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr - testsuite/tests/typecheck/should_fail/DoExpansion1.stderr - testsuite/tests/typecheck/should_fail/DoExpansion2.stderr - testsuite/tests/typecheck/should_fail/T10971d.stderr - testsuite/tests/typecheck/should_fail/T13311.stderr - testsuite/tests/typecheck/should_fail/T24064.stderr - testsuite/tests/typecheck/should_fail/T3613.stderr - testsuite/tests/typecheck/should_fail/T7851.stderr - testsuite/tests/typecheck/should_fail/T8603.stderr - testsuite/tests/typecheck/should_fail/T9612.stderr - testsuite/tests/typecheck/should_fail/tcfail128.stderr - testsuite/tests/typecheck/should_fail/tcfail168.stderr - testsuite/tests/warnings/should_fail/CaretDiagnostics1.stderr The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b312c7ba5b6b358c124e2c633fecd6f... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b312c7ba5b6b358c124e2c633fecd6f... You're receiving this email because of your account on gitlab.haskell.org.