ghc -M fails to correctly account for indirect SOURCE imports
Consider a program such as:
--- in the unit1 unit
-- Foo.hs-boot
module Foo where
foo :: String
-- Foo.hs
module Foo where
foo :: String
foo = "hi"
-- ... additional cyclic bindings here which make `Foo.hs-boot` necessary
-- Bar.hs
module Bar where
import {-# SOURCE #-} Foo
bar = ... foo ...
--- in the unit2 unit
-- Baz.hs
module Baz where
import Bar
baz = ... bar ...
Imagine running ghc -M
on Baz.hs
. It will contain something like the following:
Baz.o : Baz.hs Bar.o
Bar.o : Bar.hs Foo.o-boot
Foo.o : Foo.hs
Foo.o-boot : Foo.hs-boot
This seems perfectly reasonable: it captures the dependency structure of the user's program.
However, if we consider what happens during one-shot compilation, we will see that it isn't quite right. Specifically, imagine that baz
get an unfolding, which will naturally contain a reference to Bar.bar
(which was SOURCE
imported). When we compile Baz
GHC will see that:
- we need a declaration for
Foo.foo
in order to unfoldBar.bar
- the user hasn't imported
Bar
directly; this means thatGHC.Iface.Load.importDecl
will callloadInterface
withImportBySystem
-
GHC.Iface.Load.loadInterface
callsGHC.Iface.Load.wantHiBootFile
to determine what it should load -
wantHiBootFile
sees thatFoo
is not in the unit currently being compiled. Consequently, it responds withNotBoot
- GHC attempts to load
Foo.hi
instead ofFoo.hi-boot
as theghc -M
output claims