Save merged signatures to disk
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:
- The old strategy: When
A
importsH
, it somehow "sees" both the interface for H fromp
, and the interface fromq
, and it merges them together on-the-fly. - 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:
- Eliminate
HscSource
distinction betweenHsBootFile
andHsigFile
: the file is always calledA.hs-boot
. Instead, the type checker simply behaves differently depending on whether or not we know what the underlying implementation ofA
is (passed in using the-sig-of
flag. If we know the underlying implementation iscontainers:Data.Map
, we compile the hs-boot file "signature-style", if we don't, we assume it'sthis-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. - We introduce a new
HscSource
type,HsBootMerge
, representing anhi
(and stubo
) 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. UnlikeHsSrcFile
andHsBootFile
,ModSummary
s that areHsBootMerge
don't have a source file. - When compiling
--make
, for all "signature-style" hs-boot files in the module graph, we generate anHsBootMerge
summary to serve as theNotBoot
node of that module name. This means if youimport A
, you're actually importing theHsBootMerge
that producesA.hi
. - 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. - 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 buildA.o
? Not withghc -c A.hs
, but withghc --merge-requirements A
. I'm not sure what the best way of solving this is.
Trac metadata
Trac field | Value |
---|---|
Version | 7.10.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |