Implementation of hsig (module signatures), per #9252
authorEdward Z. Yang <ezyang@cs.stanford.edu>
Thu, 7 Aug 2014 17:32:12 +0000 (18:32 +0100)
committerEdward Z. Yang <ezyang@cs.stanford.edu>
Fri, 24 Oct 2014 22:49:41 +0000 (15:49 -0700)
commitaa4799534225e3fc6bbde0d5e5eeab8868cc3111
tree60d77acae2286263a1c75d87d93d333bce5b01c0
parent5bb73d79a83bca57dc431421ca1e022f34b8dec9
Implementation of hsig (module signatures), per #9252

Summary:
Module signatures, like hs-boot files, are Haskell modules which omit
value definitions and contain only signatures.  This patchset implements
one particular aspect of module signature, namely compiling them against
a concrete implementation.  It works like this: when we compile an hsig
file, we must be told (via the -sig-of flag) what module this signature
is implementing.  The signature is compiled into an interface file which
reexports precisely the entities mentioned in the signature file.  We also
verify that the interface is compatible with the implementation.

This feature is useful in a few situations:

    1. Like explicit import lists, signatures can be used to reduce
    sensitivity to upstream changes.  However, a signature can be defined
    once and then reused by many modules.

    2. Signatures can be used to quickly check if a new upstream version
    is compatible, by typechecking just the signatures and not the actual
    modules.

    3. A signature can be used to mediate separate modular development,
    where the signature is used as a placeholder for functionality which
    is loaded in later.  (This is only half useful at the moment, since
    typechecking against signatures without implementations is not implemented
    in this patchset.)

Unlike hs-boot files, hsig files impose no performance overhead.

This patchset punts on the type class instances (and type families) problem:
instances simply leak from the implementation to the signature.  You can
explicitly specify what instances you expect to have, and those will be checked,
but you may get more instances than you asked for.  Our eventual plan is
to allow hiding instances, but to consider all transitively reachable instances
when considering overlap and soundness.

ToDo: signature merging: when a module is provided by multiple signatures
for the same base implementation, we should not consider this ambiguous.

ToDo: at the moment, signatures do not constitute use-sites, so if you
write a signature for a deprecated function, you won't get a warning
when you compile the signature.

Future work: The ability to feed in shaping information so that we can take
advantage of more type equalities than might be immediately evident.

Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
Test Plan: validate and new tests

Reviewers: simonpj, simonmar, hvr, austin

Subscribers: simonmar, relrod, ezyang, carter, goldfire

Differential Revision: https://phabricator.haskell.org/D130

GHC Trac Issues: #9252
78 files changed:
compiler/basicTypes/Name.lhs
compiler/deSugar/Desugar.lhs
compiler/iface/LoadIface.lhs
compiler/iface/MkIface.lhs
compiler/iface/TcIface.lhs
compiler/main/DriverPhases.hs
compiler/main/DriverPipeline.hs
compiler/main/DynFlags.hs
compiler/main/Finder.lhs
compiler/main/GhcMake.hs
compiler/main/HscMain.hs
compiler/main/HscTypes.lhs
compiler/main/TidyPgm.lhs
compiler/rename/RnBinds.lhs
compiler/rename/RnEnv.lhs
compiler/rename/RnNames.lhs
compiler/typecheck/Inst.lhs
compiler/typecheck/TcBinds.lhs
compiler/typecheck/TcDeriv.lhs
compiler/typecheck/TcEnv.lhs
compiler/typecheck/TcInstDcls.lhs
compiler/typecheck/TcRnDriver.lhs
compiler/typecheck/TcRnMonad.lhs
compiler/typecheck/TcRnTypes.lhs
compiler/typecheck/TcTyClsDecls.lhs
compiler/types/InstEnv.lhs
docs/users_guide/separate_compilation.xml
testsuite/.gitignore
testsuite/tests/driver/recomp014/Makefile [new file with mode: 0644]
testsuite/tests/driver/recomp014/all.T [new file with mode: 0644]
testsuite/tests/driver/recomp014/recomp014.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof01/A.hs [new file with mode: 0644]
testsuite/tests/driver/sigof01/B.hsig [new file with mode: 0644]
testsuite/tests/driver/sigof01/Main.hs [new file with mode: 0644]
testsuite/tests/driver/sigof01/Makefile [new file with mode: 0644]
testsuite/tests/driver/sigof01/all.T [new file with mode: 0644]
testsuite/tests/driver/sigof01/sigof01.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof01/sigof01m.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof02/Double.hs [new file with mode: 0644]
testsuite/tests/driver/sigof02/Main.hs [new file with mode: 0644]
testsuite/tests/driver/sigof02/Makefile [new file with mode: 0644]
testsuite/tests/driver/sigof02/Map.hsig [new file with mode: 0644]
testsuite/tests/driver/sigof02/MapAsSet.hsig [new file with mode: 0644]
testsuite/tests/driver/sigof02/all.T [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02.stderr [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02d.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02dm.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02dmt.stderr [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02dmt.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02dt.stderr [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02m.stderr [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02m.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof02/sigof02mt.stdout [new file with mode: 0644]
testsuite/tests/driver/sigof03/A.hs [new file with mode: 0644]
testsuite/tests/driver/sigof03/ASig1.hsig [new file with mode: 0644]
testsuite/tests/driver/sigof03/ASig2.hsig [new file with mode: 0644]
testsuite/tests/driver/sigof03/Main.hs [new file with mode: 0644]
testsuite/tests/driver/sigof03/Makefile [new file with mode: 0644]
testsuite/tests/driver/sigof03/all.T [new file with mode: 0644]
testsuite/tests/driver/sigof04/Makefile [new file with mode: 0644]
testsuite/tests/driver/sigof04/Sig.hsig [new file with mode: 0644]
testsuite/tests/driver/sigof04/all.T [new file with mode: 0644]
testsuite/tests/driver/sigof04/sigof04.stderr [new file with mode: 0644]
testsuite/tests/ghci/scripts/T5979.stderr
testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout
testsuite/tests/typecheck/should_compile/all.T
testsuite/tests/typecheck/should_compile/tc264.hsig [new file with mode: 0644]
testsuite/tests/typecheck/should_compile/tc264.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/all.T
testsuite/tests/typecheck/should_fail/tcfail219.hsig [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail219.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail220.hsig [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail220.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail221.hsig [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail221.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail222.hsig [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/tcfail222.stderr [new file with mode: 0644]