summaryrefslogtreecommitdiff
path: root/compiler/iface
diff options
context:
space:
mode:
authorEdward Z. Yang <ezyang@cs.stanford.edu>2016-10-17 14:06:18 -0700
committerEdward Z. Yang <ezyang@cs.stanford.edu>2016-10-17 23:41:25 -0700
commit8fa2cdb16c4db8141b889f2364d8e5fccc62cde3 (patch)
tree9c23367c8239311feaf835d331b8790f3ef742af /compiler/iface
parentcf5eec3eaa638719fd9768c20271f8aa2b2eac1f (diff)
downloadhaskell-8fa2cdb16c4db8141b889f2364d8e5fccc62cde3.tar.gz
Track dep_finsts in exports hash, as it affects downstream deps.
Summary: I also added some more comments about the orphan and family instance hashing business. Fixes #12723. Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu> Test Plan: validate Reviewers: bgamari, austin Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2607 GHC Trac Issues: #12723
Diffstat (limited to 'compiler/iface')
-rw-r--r--compiler/iface/MkIface.hs61
1 files changed, 61 insertions, 0 deletions
diff --git a/compiler/iface/MkIface.hs b/compiler/iface/MkIface.hs
index 1a191dbb45..219d905f46 100644
--- a/compiler/iface/MkIface.hs
+++ b/compiler/iface/MkIface.hs
@@ -569,6 +569,7 @@ addFingerprints hsc_env mb_old_fingerprint iface0 new_decls
-- tracked by the usage on the ABI hash of package modules that we import.
let orph_mods
= filter (/= this_mod) -- Note [Do not update EPS with your own hi-boot]
+ -- TODO: the line below is not correct, see #12733
. filter ((== this_pkg) . moduleUnitId)
$ dep_orphs sorted_deps
dep_orphan_hashes <- getOrphanHashes hsc_env orph_mods
@@ -592,11 +593,41 @@ addFingerprints hsc_env mb_old_fingerprint iface0 new_decls
orphan_hash,
dep_orphan_hashes,
dep_pkgs (mi_deps iface0),
+ -- See Note [Export hash depends on non-orphan family instances]
+ dep_finsts (mi_deps iface0),
-- dep_pkgs: see "Package Version Changes" on
-- wiki/Commentary/Compiler/RecompilationAvoidance
mi_trust iface0)
-- Make sure change of Safe Haskell mode causes recomp.
+ -- Note [Export hash depends on non-orphan family instances]
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ --
+ -- Suppose we have:
+ --
+ -- module A where
+ -- type instance F Int = Bool
+ --
+ -- module B where
+ -- import A
+ --
+ -- module C where
+ -- import B
+ --
+ -- The family instance consistency check for C depends on the dep_finsts of
+ -- B. If we rename module A to A2, when the dep_finsts of B changes, we need
+ -- to make sure that C gets rebuilt. Effectively, the dep_finsts are part of
+ -- the exports of B, because C always considers them when checking
+ -- consistency.
+ --
+ -- A full discussion is in #12723.
+ --
+ -- We do NOT need to hash dep_orphs, because this is implied by
+ -- dep_orphan_hashes, and we do not need to hash ordinary class instances,
+ -- because there is no eager consistency check as there is with type families
+ -- (also we didn't store it anywhere!)
+ --
+
-- put the declarations in a canonical order, sorted by OccName
let sorted_decls = Map.elems $ Map.fromList $
[(getOccName d, e) | e@(_, d) <- decls_w_hashes]
@@ -664,6 +695,36 @@ addFingerprints hsc_env mb_old_fingerprint iface0 new_decls
fix_fn = mi_fix_fn iface0
ann_fn = mkIfaceAnnCache (mi_anns iface0)
+-- | Retrieve the orphan hashes 'mi_orphan_hash' for a list of modules
+-- (in particular, the orphan modules which are transitively imported by the
+-- current module).
+--
+-- Q: Why do we need the hash at all, doesn't the list of transitively
+-- imported orphan modules suffice?
+--
+-- A: If one of our transitive imports adds a new orphan instance, our
+-- export hash must change so that modules which import us rebuild. If we just
+-- hashed the [Module], the hash would not change even when a new instance was
+-- added to a module that already had an orphan instance.
+--
+-- Q: Why don't we just hash the orphan hashes of our direct dependencies?
+-- Why the full transitive closure?
+--
+-- A: Suppose we have these modules:
+--
+-- module A where
+-- instance Show (a -> b) where
+-- module B where
+-- import A -- **
+-- module C where
+-- import A
+-- import B
+--
+-- Whether or not we add or remove the import to A in B affects the
+-- orphan hash of B. But it shouldn't really affect the orphan hash
+-- of C. If we hashed only direct dependencies, there would be no
+-- way to tell that the net effect was a wash, and we'd be forced
+-- to recompile C and everything else.
getOrphanHashes :: HscEnv -> [Module] -> IO [Fingerprint]
getOrphanHashes hsc_env mods = do
eps <- hscEPS hsc_env