[GHC] #10690: Save merged signatures to disk

GHC ghc-devs at haskell.org
Sat Jul 25 20:48:03 UTC 2015


#10690: Save merged signatures to disk
-------------------------------------+-------------------------------------
              Reporter:  ezyang      |             Owner:
                  Type:  bug         |            Status:  new
              Priority:  normal      |         Milestone:
             Component:  Compiler    |           Version:  7.10.1
              Keywords:  backpack    |  Operating System:  Unknown/Multiple
          Architecture:              |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
             Test Case:              |        Blocked By:
              Blocking:              |   Related Tickets:
Differential Revisions:              |
-------------------------------------+-------------------------------------
 The Backpack model of development encourages users to mix signatures
 together. For example:

 {{{
 unit p where
   signature H where x :: Int
 unit q where
   signature H where y :: Int
 unit r where
   include p
   include q
   module A where import H(x,y)
 }}}

 When `A` imports `H`, it should see both `x` and `y` (i.e. a merged
 version of the two signatures.)  There are two possible ways to implement
 this:

 1. The old strategy: When `A` imports `H`, it somehow "sees" both the
 interface for H from `p`, and the interface from `q`, and it merges them
 together on-the-fly.
 2. The new strategy: Before compiling `A`, we merge the interfaces
 together, and use that merged interface as what A imports and gets its
 export from.

 Strategy (2) has a few advantages: in separate compilation, it avoids the
 need to repeatedly merge interfaces together, and it also simplifies GHC
 in that we don't have to manage on the fly signature merging.

 Now the challenge: GHC currently assumes that every build product is
 associated with a source file: however, merged interface files don't have
 this property. Both `--make` and one-shot `-c` compilation infrastructure
 is organized around this property.

 Here's is the proposal for how to slot this in:

 1. Eliminate `HscSource` distinction between `HsBootFile` and `HsigFile`:
 the file is always called `A.hs-boot`.  Instead, the type checker simply
 behaves differently depending on whether or not we know what the
 underlying implementation of `A` is (passed in using the `-sig-of` flag.
 If we know the underlying implementation is `containers:Data.Map`, we
 compile the hs-boot file "signature-style", if we don't, we assume it's
 `this-package:A` and compile it "boot-style" (Conceivably for cross-unit
 mutual recursion this will need to be more sophisticated, but this will do
 for now.)  By the way, this means that all signature files now compile to
 A.hi-boot.

 2. We introduce a new `HscSource` type, `HsBootMerge`, representing an
 `hi` (and stub `o`) file that will be generated by a signature merge.
 Intuitively, this operation will merge together A.hi-boot as well as any
 signatures which were brought into scope by a `-package` flag.  Unlike
 `HsSrcFile` and `HsBootFile`, `ModSummary`s that are `HsBootMerge` don't
 have a source file.

 3. When compiling `--make`, for all "signature-style" hs-boot files in the
 module graph, we generate an `HsBootMerge` summary to serve as the
 `NotBoot` node of that module name.  This means if you `import A`, you're
 actually importing the `HsBootMerge` that produces `A.hi`.

 4. When compiling one-shot, we have a new command for generating the
 `HsBootMerge`: `ghc --merge-requirements A`.  This will go and look for an
 A.hi-boot as well as any external signatures and merge them together.
 Note that we can't use the existing compilation pipeline `-c` to generate
 merged hs-boot files, since these presuppose that there is some input
 source file, which there is none in this case.

 5. When generating a Makefile dependency graph, an entry for an
 `HsBootMerge` looks like this:
 {{{
 A.o : A.hi-boot
 A.o : /path/to/ghc/foo-0.1/A.hi # if -include-pkg-deps is added
 }}}
    That is to say, an `HsBootMerge` looks like a normal source file that
 imports each signature it's merging together, but doesn't have a source
 file associated with it.  One downside with this representation is that it
 makes Makefile rules a little more complicated: how do you build `A.o`?
 Not with `ghc -c A.hs`, but with `ghc --merge-requirements A`.  I'm not
 sure what the best way of solving this is.

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


More information about the ghc-tickets mailing list