Skip to content

Commit c3caebc

Browse files
committed
Fix hd-view package-qualified imports bypassing home-unit
See Note [Do not package-qualify imports for home units] Fixes #283
1 parent 5f3434e commit c3caebc

1 file changed

Lines changed: 34 additions & 5 deletions

File tree

haskell-debugger/GHC/Debugger/Monad.hs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ import GHC.Platform.Ways
9494
import GHC.Data.FastString.Env (emptyFsEnv)
9595
#endif
9696

97+
import GHC.Unit.Home.Graph
98+
9799
-- | A debugger action.
98100
newtype Debugger a = Debugger { unDebugger :: ReaderT DebuggerState GHC.Ghc a }
99101
deriving ( Functor, Applicative, Monad, MonadIO
@@ -428,11 +430,13 @@ runDebugger l rootDir compDir libdir units ghcInvocation' extraGhcArgs mainFp co
428430
let preludeImp = GHC.IIDecl . GHC.simpleImportDecl $ GHC.mkModuleName "Prelude"
429431
-- dbgView should always be available, either because we manually loaded it
430432
-- or because it's in the transitive closure.
433+
hug <- hsc_HUG <$> getSession
431434
let dbgViewImps
432-
-- Using in-memory hs-dbg-view. It's a home-unit, so refer to it directly
433-
| hdv_uid == hsDebuggerViewInMemoryUnitId
435+
-- If hs-dbg-view is a home-unit, refer to it directly
436+
-- See Note [Do not package-qualify imports for home units]
437+
| memberHugUnitId hdv_uid hug
434438
= map (GHC.IIModule . mkModule (RealUnit (Definite hdv_uid))) loadedBuiltinModNames
435-
-- It's available in a unit in the transitive closure. Resolve it.
439+
-- It's available in an exposed unit in the transitive closure. Resolve it
436440
| otherwise
437441
= map (\mn ->
438442
GHC.IIDecl (GHC.simpleImportDecl mn)
@@ -507,9 +511,7 @@ add our own `MC.finally cleanupInterp` call which sends the `Shutdown` message
507511
to the external interpreter before propagating the exception further (to GHC's
508512
`withCleanupSession`, which will now do Nothing because we set `InterpPending`,
509513
and beyond).
510-
-}
511514
512-
{-
513515
Note [Must explicitly expose module graph units]
514516
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
515517
`interactiveGhcDebugger` is our "current home unit", so its
@@ -533,6 +535,33 @@ An alternative, closer to what ghci does, would be to copy the `packageFlags`
533535
from the debuggee units, however doing so doesn't take care of fixing a unitId
534536
for dependencies of dependencies.
535537
538+
Note [Do not package-qualify imports for home units]
539+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540+
A package-qualified module import will be looked up directly in the exposed
541+
packages, IGNORING the home units modules.
542+
543+
This can lead to two scenarios:
544+
545+
1) a package-import of a loaded unit fails, because that unit, despite being
546+
loaded, is not installed
547+
548+
2) a package-import of a loaded unit succeeds, because a unit with the same
549+
name (but not necessarily the same unit-id!), is installed.
550+
551+
The second case can result in subtly wrong interactive sessions, where the
552+
package-qualified imported module shadows the loaded module. Perhaps GHC could
553+
warn about this. Cabal-repl and ghci also suffer from this subtle interaction.
554+
555+
In light of this, when the debugger imports the `haskell-debugger-view` modules,
556+
it is imperative that if the `haskell-debugger-view` unit is in the home units
557+
(e.g. if `haskell-debugger-view` is listed in the cabal.project, like it is in
558+
the debugger tree), we do not use a package-qualified import.
559+
560+
On the other hand, if the `haskell-debugger-view` package is not in the
561+
home-units, we *should* package-qualify it to make sure we reference the right
562+
one.
563+
564+
See also #283
536565
-}
537566

538567
-- | See Note [Shutting down the external interpreter]

0 commit comments

Comments
 (0)