summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-05-28 17:16:18 -0400
committerBen Gamari <ben@smart-cactus.org>2020-05-29 21:05:56 -0400
commit8d428a9a0b2cbcfdd4f86d7d64cd73cf6350556b (patch)
tree77167bc0c0762f9a1697708ae2d3ef33140188ff
parentd6203f24cf421749616a247c047a9b44192f963a (diff)
downloadhaskell-wip/T14482.tar.gz
ghc -M: Ensure that .hs-boot files are built before .hs fileswip/T14482
See Note [Ensure hs-boot files are built before source files]. Fixes #14882.
-rw-r--r--compiler/GHC/Driver/MakeFile.hs51
1 files changed, 43 insertions, 8 deletions
diff --git a/compiler/GHC/Driver/MakeFile.hs b/compiler/GHC/Driver/MakeFile.hs
index f0de5b75c8..ab5d231b7f 100644
--- a/compiler/GHC/Driver/MakeFile.hs
+++ b/compiler/GHC/Driver/MakeFile.hs
@@ -93,7 +93,9 @@ doMkDependHS srcs = do
-- and complaining about cycles
hsc_env <- getSession
root <- liftIO getCurrentDirectory
- mapM_ (liftIO . processDeps dflags hsc_env excl_mods root (mkd_tmp_hdl files)) sorted
+
+ mapM_ (liftIO . processDeps dflags hsc_env (mgBootModules module_graph)
+ excl_mods root (mkd_tmp_hdl files)) sorted
-- If -ddump-mod-cycles, show cycles in the module graph
liftIO $ dumpModCycles dflags module_graph
@@ -178,10 +180,11 @@ beginMkDependHS dflags = do
processDeps :: DynFlags
-> HscEnv
- -> [ModuleName]
- -> FilePath
- -> Handle -- Write dependencies to here
- -> SCC ModSummary
+ -> ModuleSet -- ^ modules with hs-boot files
+ -> [ModuleName] -- ^ modules to exclude
+ -> FilePath -- ^ root directory
+ -> Handle -- ^ Write dependencies to here
+ -> SCC ModSummary -- ^ a SCC of dependent modules
-> IO ()
-- Write suitable dependencies to handle
-- Always:
@@ -198,11 +201,11 @@ processDeps :: DynFlags
--
-- For {-# SOURCE #-} imports the "hi" will be "hi-boot".
-processDeps dflags _ _ _ _ (CyclicSCC nodes)
+processDeps dflags _ _ _ _ _ (CyclicSCC nodes)
= -- There shouldn't be any cycles; report them
throwGhcExceptionIO (ProgramError (showSDoc dflags $ GHC.cyclicModuleErr nodes))
-processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC node)
+processDeps dflags hsc_env boot_mods excl_mods root hdl (AcyclicSCC node)
= do { let extra_suffixes = depSuffixes dflags
include_pkg_deps = depIncludePkgDeps dflags
src_file = msHsFilePath node
@@ -249,9 +252,41 @@ processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC node)
; do_imps True (ms_srcimps node)
; do_imps False (ms_imps node)
- }
+ -- For each module with a hs-boot file, emit a
+ -- dependency from the object to the hi-boot file.
+ -- See Note [Ensure hs-boot files are built before
+ -- source files].
+ ; case (ms_hsc_src, has_boot_file node) of
+ (HsSrcFile, Just hs_boot_loc) ->
+ writeDependency root hdl obj_files (ml_hi_file hs_boot_loc)
+ _ -> return ()
+ }
+ where
+ has_boot_file :: ModSummary -> Maybe ModLocation
+ has_boot_file ms
+ | ms_mod ms `elemModuleSet` boot_mods
+ = Just $ addBootSuffixLocn (ms_location ms)
+ | otherwise
+ = Nothing
+
+-- Note [Ensure hs-boot files are built before source files]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- In general we need to take care to ensure that `.hs-boot` files
+-- are built before their associated `.hs` files. The reason is that
+-- the existence of a .hi-boot file will affect the code generated
+-- during the compilation of the .hs file. If the .hi-boot file is *not*
+-- built prior to the .hs file then you can end up with situations like
+-- #14481, where the logic which makes DFun decls work in boot files
+-- fails to fire (see Note [DFun impedance matching] and Note [DFun
+-- knot-tying] in GHC.Tc.Module.
+--
+-- Consequently, we inject "artificial" dependencies from objects to
+-- the hi-boot files of any modules which produced the object. This avoids
+-- #14481 and #14482.
+--
+
findDependency :: HscEnv
-> SrcSpan
-> Maybe FastString -- package qualifier, if any