[GHC] #14396: Hs-boot woes during family instance consistency checks

GHC ghc-devs at haskell.org
Tue Oct 31 11:28:04 UTC 2017


#14396: Hs-boot woes during family instance consistency checks
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.1
      Resolution:                    |             Keywords:  hs-boot
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 Gah!  This is ridiculously complicated.  Surely there must be a better
 way.

 In thinking about this I realised:

 * A very similar danger happens for ordinary data type decls:
 {{{
     M.hs-boot    data S

     M1.hs        import {-# SOURCE #-} M
                  data D (a::S) = ...

     M.hs         import M1
                  data T a = MkT (D a)
                  data S = A | B
 }}}
   The danger is that we'll kind-check the decl for T,
   suck in the interface decl for T1, and then find that S
   is not yet in the type envt.

   But we fixed that (conservatively) in `RnSource.addBootDeps`;
   `Note [Extra dependencies from .hs-boot files]` in `RnSource`

 * Even within one module we have an open ticket about when to
   typecheck 'type instance' decls: #12088.  It has a very similar
   flavour to the Edward's solution here.

 * Edward's solution defers the type family consistency check, but the
   interface-file instance is there in the family-instance environment
   all the time.  e.g.
 {{{
      M.hs-boot   data SyntaxExpr

      M1.hs       import {-# SOURCE #-} M
                  instance F Int = SyntaxExpr

      M.hs        import M1
                  data T = ...(F Int)...
                  data SyntaxExpr = SE
 }}}
   I'm worried that an "earlier" decl, for T, might make use of that
   instance, which would again prematurely look for SyntaxExpr in
   the M's type environment, before it has been looked at.

   Oh -- but maybe it's (just) ok: the fix in addBootDeps will ensure
   that SyntaxExpr is typechecked before T.  But it's terribly delicate.

 I did have one simplifying idea.  Thought experiment:

 * When typechecking M, begin by loading M.hi-boot (which we already do)
   /and/ extend the type environment.  So we'll add `SyntaxExpr` and `W`,
   in the above examples, to the type envt.

 * Do none of this addBootDeps stuff, nor deferring family instances.
   If we need `W` or `SyntaxExpr` before they've been encountered, we'll
 use
   the boot-versions.

 * So when compiling M we'll have places where we only have the boot TyCon
   instead of the real TyCon.  Maybe that does not matter?

 * When we are all done, we'll spit out a M.hi file.

 * In --make mode we'll now re-typecheck the loop from the .hi files,
   building all the knots just as expected.

 This is much much simpler.  Would it work?  Worth a a try?

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14396#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list