diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2020-04-30 11:09:24 -0400 |
---|---|---|
committer | Cale Gibbard <cgibbard@gmail.com> | 2020-12-28 12:28:35 -0500 |
commit | 2113a1d600e579bb0f54a0526a03626f105c0365 (patch) | |
tree | 746a62bb019f399f3921fdfb1f1f15ae521f6c90 /compiler/GHC/Driver/MakeFile.hs | |
parent | cbc7c3dda6bdf4acb760ca9eb545faeb98ab0dbe (diff) | |
download | haskell-2113a1d600e579bb0f54a0526a03626f105c0365.tar.gz |
Put hole instantiation typechecking in the module graph and fix driver batch mode backpack edges
Backpack instantiations need to be typechecked to make sure that the
arguments fit the parameters. `tcRnInstantiateSignature` checks
instantiations with concrete modules, while `tcRnCheckUnit` checks
instantiations with free holes (signatures in the current modules).
Before this change, it worked that `tcRnInstantiateSignature` was called
after typechecking the argument module, see `HscMain.hsc_typecheck`,
while `tcRnCheckUnit` was called in `unsweep'` where-bound in
`GhcMake.upsweep`. `tcRnCheckUnit` was called once per each
instantiation once all the argument sigs were processed. This was done
with simple "to do" and "already done" accumulators in the fold.
`parUpsweep` did not implement the change.
With this change, `tcRnCheckUnit` instead is associated with its own
node in the `ModuleGraph`. Nodes are now:
```haskell
data ModuleGraphNode
-- | Instantiation nodes track the instantiation of other units
-- (backpack dependencies) with the holes (signatures) of the current package.
= InstantiationNode InstantiatedUnit
-- | There is a module summary node for each module, signature, and boot module being built.
| ModuleNode ExtendedModSummary
```
instead of just `ModSummary`; the `InstantiationNode` case is the
instantiation of a unit to be checked. The dependencies of such nodes
are the same "free holes" as was checked with the accumulator before.
Both versions of upsweep on such a node call `tcRnCheckUnit`.
There previously was an `implicitRequirements` function which would
crawl through every non-current-unit module dep to look for all free
holes (signatures) to add as dependencies in `GHC.Driver.Make`. But this
is no good: we shouldn't be looking for transitive anything when
building the graph: the graph should only have immediate edges and the
scheduler takes care that all transitive requirements are met.
So `GHC.Driver.Make` stopped using `implicitRequirements`, and instead
uses a new `implicitRequirementsShallow`, which just returns the
outermost instantiation node (or module name if the immediate dependency
is itself a signature). The signature dependencies are just treated like
any other imported module, but the module ones then go in a list stored
in the `ModuleNode` next to the `ModSummary` as the "extra backpack
dependencies". When `downsweep` creates the mod summaries, it adds this
information too.
------
There is one code quality, and possible correctness thing left: In
addition to `implicitRequirements` there is `findExtraSigImports`, which
says something like "if you are an instantiation argument (you are
substituted or a signature), you need to import its things too". This
is a little non-local so I am not quite sure how to get rid of it in
`GHC.Driver.Make`, but we probably should eventually.
First though, let's try to make a test case that observes that we don't
do this, lest it actually be unneeded. Until then, I'm happy to leave it
as is.
------
Beside the ability to use `-j`, the other major user-visibile side
effect of this change is that that the --make progress log now includes
"Instantiating" messages for these new nodes. Those also are numbered
like module nodes and count towards the total.
------
Fixes #17188
Updates hackage submomdule
Metric Increase:
T12425
T13035
Diffstat (limited to 'compiler/GHC/Driver/MakeFile.hs')
-rw-r--r-- | compiler/GHC/Driver/MakeFile.hs | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/compiler/GHC/Driver/MakeFile.hs b/compiler/GHC/Driver/MakeFile.hs index 86262c5ab4..b54bbbea3e 100644 --- a/compiler/GHC/Driver/MakeFile.hs +++ b/compiler/GHC/Driver/MakeFile.hs @@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} ----------------------------------------------------------------------------- -- @@ -186,7 +187,7 @@ processDeps :: DynFlags -> [ModuleName] -> FilePath -> Handle -- Write dependencies to here - -> SCC ModSummary + -> SCC ModuleGraphNode -> IO () -- Write suitable dependencies to handle -- Always: @@ -205,9 +206,17 @@ processDeps :: DynFlags processDeps dflags _ _ _ _ (CyclicSCC nodes) = -- There shouldn't be any cycles; report them - throwGhcExceptionIO (ProgramError (showSDoc dflags $ GHC.cyclicModuleErr nodes)) + throwGhcExceptionIO $ ProgramError $ + showSDoc dflags $ GHC.cyclicModuleErr nodes -processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC node) +processDeps dflags _ _ _ _ (AcyclicSCC (InstantiationNode node)) + = -- There shouldn't be any backpack instantiations; report them as well + throwGhcExceptionIO $ ProgramError $ + showSDoc dflags $ + vcat [ text "Unexpected backpack instantiation in dependency graph while constructing Makefile:" + , nest 2 $ ppr node ] + +processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC (ModuleNode (ExtendedModSummary node _))) = do { let extra_suffixes = depSuffixes dflags include_pkg_deps = depIncludePkgDeps dflags src_file = msHsFilePath node @@ -371,10 +380,12 @@ dumpModCycles dflags module_graph | otherwise = putMsg dflags (hang (text "Module cycles found:") 2 pp_cycles) where + topoSort = filterToposortToModules $ + GHC.topSortModuleGraph True module_graph Nothing cycles :: [[ModSummary]] cycles = - [ c | CyclicSCC c <- GHC.topSortModuleGraph True module_graph Nothing ] + [ c | CyclicSCC c <- topoSort ] pp_cycles = vcat [ (text "---------- Cycle" <+> int n <+> ptext (sLit "----------")) $$ pprCycle c $$ blankLine @@ -402,8 +413,8 @@ pprCycle summaries = pp_group (CyclicSCC summaries) loop_breaker = head boot_only all_others = tail boot_only ++ others - groups = - GHC.topSortModuleGraph True (mkModuleGraph all_others) Nothing + groups = filterToposortToModules $ + GHC.topSortModuleGraph True (mkModuleGraph $ extendModSummaryNoDeps <$> all_others) Nothing pp_ms summary = text mod_str <> text (take (20 - length mod_str) (repeat ' ')) <+> (pp_imps empty (map snd (ms_imps summary)) $$ |