Skip to content

recompilation can fail to recheck type family instance consistency

Suppose I have two modules I1 and I2 that define instances for the same type family and I have a module M consisting solely of

module M where
import I1
import I2

When GHC compiles M it checks that the type family instances of I1 are consistent with those from I2. Then it writes out M.hi which is treated as a certificate that the type family instances of I1 and I2 are compatible:

How do we know which pairs of modules have already been checked?  Any pair of
modules where both modules occur in the `HscTypes.dep_finsts' set (of the
`HscTypes.Dependencies') of one of our directly imported modules must have
already been checked.  Everything else, we check now.  (So that we can be
certain that the modules in our `HscTypes.dep_finsts' are consistent.)

That means in particular that another module that imports M doesn't have to check family instance consistency between I1 and I2. (Imagine I1 and I2 are two internal modules of a library and M is its top-level interface that just re-exports things.)

Now suppose I edit I2 in a way that makes its type family instances no longer consistent with those of I1, then recompile I2 and then M in one-shot mode. Since M did not really use anything from I2, ghc concludes that recompilation of M is not required. But now the M.hi file is incorrect as a certificate that I1 and I2 have consistent instances and a consumer of M would be able to see the inconsistency even if it uses parts of I1 and I2 that changed.

Two possible ways to address this:

  1. Since M.hi represents a certificate of consistency between I1 and I2, M should be considered to "use" the family instances so that it is recompiled when the instances change.
  2. When determining which pairs of modules we don't need to check for consistency in FamInst, we take some interface hash into account to make sure that the versions of (in this case) I1 and I2 that were checked for consistency when we compiled M are the same ones that we are importing in our client of M.

I think we might want both of these, but especially the second one. This might ideally involve adding a "type family instances hash" to the interface file if it doesn't already exist.

Trac metadata
Trac field Value
Version 8.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information