Fix: `:load` ignores ghci command line argument settings for import paths

Depends on !15888 (closed)

Honour -i<path> cli arguments to GHCi in prompt and session home unit

The idea is that we no longer clear the importPaths of the interactive-session so that when you load :load, the importPaths are honoured that are passed on the top-level cli.

We introduce a notion of "base" DynFlags that both the ghci prompt and the interactive session inherit from.

Some consequences:

  • ghc -isrc A and
  • ghc -unit @"-isrc A" (where @"..." means the contents of a response file)

are behaving differently! In the first case, -isrc will be inherited in the interactive session and on the prompt.

Commands such as

:load Mod

will then look for Mod in src.

In the second case, the -isrc are solely for the home unit and not for the interactive session. Thus,

:load Mod

will only look for Mod in ., not in src.

It is our goal that there is as little special logic in GHCi to handle multiple home units vs a single home unit case as possible. Therefore, we try to come up with abstractions and implementations that allow us to treat these two cases the same. This PR upholds this goal, at the cost of a slightly more complicated notion what the cli invocation actually means for the home units and GHCi session.

This design allows us now to:

  • Reliably change the importPaths of the interactive session.
  • Change the ghc-options of the home unit
  • Intuitive behaviour of loading modules and adding modules to the current context
  • Correct multiple home unit sessions

Use home unit package db stacks in GHCi prompt and session unit

While fixing this issue, we uncovered a related issue that the fix made worse, so we fix in this MR as well.

In order to import modules from home unit dependencies (e.g., Data.Map), the ghci prompt unit needs to populate its UnitState. This is tricky to handle correctly, which PackageDBFlags should we use to populate the UnitState? We decide, the most intuitive solution for users is to depend on all PackageDBFlags, so that any dependency can be imported in GHCi. This assumes consistency in the PackageDBFlags, so no two home units specify PackageDBFlags that are inconsistent with each other.

We could simply concat all the PackageDBFlags of the existing home units, but later PackageDBFlags shadow earlier ones, leading to the last processed home units' PackageDBFlags to shadow the earlier ones. This is hard to fix, we need to give users the capability to provide ghc options for the ghci prompt home unit. However, as this is considerably more work, we decided on an approximation that should work out most of the time.

Package Db stacks in cabal and stack follow a certain structure:

-no-user-package-db > -package-db $cabal-store > -package-db $local-db

The first two arguments are always the same, namely the -no-user-package-db and -package-db $cabal-store. We compute the longest common prefix over all home units, and use that as the start of the package db stack. Then, over the rest of the PackageDBFlags, we simply take the union and append them to our initial stack. We assume, that this rest of package dbs only defines very few, "local" units that are usually not shadowing each other.

This allows us to get a relatively consistent package database stack for the ghci prompt home unit. We do something similar for -package flags, to make sure only the correct units are actually visible in the ghci session. This time, we simply take the union of all PackageFlags, allowing us to import modules from the home unit dependencies.

In the future, it would be beneficial to allow the user to provide the exact ghc options to control the visibilities. For now, this will have to do.

Closes #27202 (closed)

Related to #26866 (closed), would have closed #26866 (closed) as well.

  • Documentation
Edited by Hannes Siebenhandl

Merge request reports

Loading