Orphan hashes are not being propagated correctly
In D2607, simonpj asked why we didn't also put class instances in the export hash. Why indeed. In the course of investigating, I discovered another bug in how we handle orphan recompilation.
Unfortunately, this bug needs two packages to manifest.
-- p/P.hs
module P where
instance Show (a -> b) where
--instance Show (IO a) where
-- q/Q.hs
module Q where
import P
-- q/Q2.hs
module Q2 where
import Q
Put in some default Cabal files, with q depending on p, and then build the entire kaboodle. Then edit p/P.hs
to uncomment the second orphan instance. Rebuild.
ezyang@sabre:~/Dev/labs/orph$ cabal new-build q -w ghc-head
In order, the following will be built (use -v for more details):
- p-0.1.0.0 (lib) (file P.hs changed)
- q-0.1.0.0 (lib) (dependency rebuilt)
Preprocessing library p-0.1.0.0...
[1 of 1] Compiling P ( P.hs, /srv/code/labs/orph/dist-newstyle/build/x86_64-linux/ghc-8.1.20161016/p-0.1.0.0/build/P.o )
P.hs:2:10: warning: [-Wmissing-methods]
• No explicit implementation for
either ‘showsPrec’ or ‘show’
• In the instance declaration for ‘Show (a -> b)’
P.hs:3:10: warning: [-Wmissing-methods]
• No explicit implementation for
either ‘showsPrec’ or ‘show’
• In the instance declaration for ‘Show (IO a)’
module Q2 where
Preprocessing library q-0.1.0.0...
[1 of 2] Compiling Q ( Q.hs, /srv/code/labs/orph/dist-newstyle/build/x86_64-linux/ghc-8.1.20161016/q-0.1.0.0/build/Q.o ) [P changed]
ezyang@sabre:~/Dev/labs/orph$
Notice: Q2 never got rebuilt. This is wrong wrong wrong: P changed, and we need to rebuild Q2!
Here are the hashes for Q.hi before and after:
-- Before
interface Q 80120161016
interface hash: 2ffc06a1552565a73c888110ab4cf8df
ABI hash: b2768862866252ea5a63401d2aa05aaa
export-list hash: 092acc280445a8bcc96904afb8b766b0
orphan hash: 693e9af84d3dfcc71e640e005bdc5e2e
flag hash: f01bb78d3c47152bc5253f256b2a60d3
-- After
interface Q 80120161016
interface hash: 009db9e5ecbe49e36b7bf38e02087e75
ABI hash: b2768862866252ea5a63401d2aa05aaa
export-list hash: 092acc280445a8bcc96904afb8b766b0
orphan hash: 693e9af84d3dfcc71e640e005bdc5e2e
flag hash: f01bb78d3c47152bc5253f256b2a60d3
The ABI hash didn't get updated.
At the moment, when we compute the export hash, we only consider the orphan hashes from the home package. Here's the comment justifying it:
-- the export hash of a module depends on the orphan hashes of the
-- orphan modules below us in the dependency tree. This is the way
-- that changes in orphans get propagated all the way up the
-- dependency tree. We only care about orphan modules in the current
-- package, because changes to orphans outside this package will be
-- tracked by the usage on the ABI hash of package modules that we import.
It is true that we know to rebuild Q.hs when P.hs changes. But that is not much solace for Q2.hs...