[Git][ghc/ghc][wip/keep-going-hs-boot] WIP: Fix driver batch mode backpack edges

cgibbard gitlab at gitlab.haskell.org
Fri Jun 26 09:49:30 UTC 2020



cgibbard pushed to branch wip/keep-going-hs-boot at Glasgow Haskell Compiler / GHC


Commits:
97684237 by John Ericson at 2020-06-26T05:49:20-04:00
WIP: Fix driver batch mode backpack edges

We previously allowed instantiations nodes to depend on signatures, but
not regular modules to depend on instantiations nodes.

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:

 - I made an `ExtendedModSummary` type alias to contain the backpack
   dependencies. It should be a real data type instead.

 - 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.

   First though, let's try to make a test case that observes that we
   don't do this, lest it actually be unneeded.

- - - - -


2 changed files:

- compiler/GHC/Driver/Make.hs
- compiler/GHC/Unit/Module.hs


Changes:

=====================================
compiler/GHC/Driver/Make.hs
=====================================
@@ -952,6 +952,12 @@ mkBuildModule ms = GWIB
   , gwib_isBoot = isBootSummary ms
   }
 
+mkHomeBuildModule :: ModSummary -> ModuleNameWithIsBoot
+mkHomeBuildModule ms = GWIB
+  { gwib_mod = moduleName $ ms_mod ms
+  , gwib_isBoot = isBootSummary ms
+  }
+
 -- | The entry point to the parallel upsweep.
 --
 -- See also the simpler, sequential 'upsweep'.
@@ -1390,20 +1396,20 @@ upsweep mHscMessage old_hpt stable_mods cleanup sccs = do
 
   keep_going this_mods old_hpt done mods mod_index nmods uids_to_check done_holes = do
     let sum_deps ms (AcyclicSCC mod) =
-          if any (flip elem . map (unLoc . snd) $ ms_imps mod) ms
-            then ms_mod_name mod:ms
+          if any (flip elem $ unfilteredEdges False mod) ms
+            then mkHomeBuildModule mod:ms
             else ms
         sum_deps ms _ = ms
         dep_closure = foldl' sum_deps this_mods mods
         dropped_ms = drop (length this_mods) (reverse dep_closure)
-        prunable (AcyclicSCC mod) = elem (ms_mod_name mod) dep_closure
+        prunable (AcyclicSCC mod) = elem (mkHomeBuildModule mod) dep_closure
         prunable _ = False
         mods' = filter (not . prunable) mods
         nmods' = nmods - length dropped_ms
 
     when (not $ null dropped_ms) $ do
         dflags <- getSessionDynFlags
-        liftIO $ fatalErrorMsg dflags (keepGoingPruneErr dropped_ms)
+        liftIO $ fatalErrorMsg dflags (keepGoingPruneErr $ gwib_mod <$> dropped_ms)
     (_, done') <- upsweep' old_hpt done mods' (mod_index+1) nmods' uids_to_check done_holes
     return (Failed, done')
 
@@ -1428,7 +1434,7 @@ upsweep mHscMessage old_hpt stable_mods cleanup sccs = do
    = do dflags <- getSessionDynFlags
         liftIO $ fatalErrorMsg dflags (cyclicModuleErr ms)
         if gopt Opt_KeepGoing dflags
-          then keep_going (map ms_mod_name ms) old_hpt done mods mod_index nmods
+          then keep_going (mkHomeBuildModule <$> ms) old_hpt done mods mod_index nmods
                           uids_to_check done_holes
           else return (Failed, done)
 
@@ -1482,7 +1488,7 @@ upsweep mHscMessage old_hpt stable_mods cleanup sccs = do
           Nothing -> do
                 dflags <- getSessionDynFlags
                 if gopt Opt_KeepGoing dflags
-                  then keep_going [ms_mod_name mod] old_hpt done mods mod_index nmods
+                  then keep_going [mkHomeBuildModule mod] old_hpt done mods mod_index nmods
                                   uids_to_check done_holes
                   else return (Failed, done)
           Just mod_info -> do
@@ -1917,7 +1923,7 @@ reachableBackwards mod summaries
   = [ node_payload node | node <- reachableG (transposeG graph) root ]
   where -- the rest just sets up the graph:
         (graph, lookup_node) = moduleGraphNodes False summaries
-        root  = expectJust "reachableBackwards" (lookup_node IsBoot mod)
+        root  = expectJust "reachableBackwards" (lookup_node $ GWIB mod IsBoot)
 
 -- ---------------------------------------------------------------------------
 --
@@ -1960,7 +1966,7 @@ topSortModuleGraph drop_hs_boot_nodes module_graph mb_root_mod
             -- the specified module.  We do this by building a graph with
             -- the full set of nodes, and determining the reachable set from
             -- the specified node.
-            let root | Just node <- lookup_node NotBoot root_mod
+            let root | Just node <- lookup_node $ GWIB root_mod NotBoot
                      , graph `hasVertexG` node
                      = node
                      | otherwise
@@ -1975,20 +1981,39 @@ summaryNodeKey = node_key
 summaryNodeSummary :: SummaryNode -> ModSummary
 summaryNodeSummary = node_payload
 
+unfilteredEdges :: Bool -> ModSummary -> [ModuleNameWithIsBoot]
+unfilteredEdges drop_hs_boot_nodes ms =
+    (flip GWIB hs_boot_key . unLoc <$> ms_home_srcimps ms) ++
+    (flip GWIB NotBoot     . unLoc <$> ms_home_imps ms) ++
+    [ GWIB (ms_mod_name ms) IsBoot
+    | not $ drop_hs_boot_nodes || ms_hsc_src ms == HsBootFile
+      -- see [boot-edges] below
+    ]
+  where
+    -- [boot-edges] if this is a .hs and there is an equivalent
+    -- .hs-boot, add a link from the former to the latter.  This
+    -- has the effect of detecting bogus cases where the .hs-boot
+    -- depends on the .hs, by introducing a cycle.  Additionally,
+    -- it ensures that we will always process the .hs-boot before
+    -- the .hs, and so the HomePackageTable will always have the
+    -- most up to date information.
+
+    -- Drop hs-boot nodes by using HsSrcFile as the key
+    hs_boot_key | drop_hs_boot_nodes = NotBoot -- is regular mod or signature
+                | otherwise          = IsBoot
+
 moduleGraphNodes :: Bool -> [ModSummary]
-  -> (Graph SummaryNode, IsBootInterface -> ModuleName -> Maybe SummaryNode)
+  -> (Graph SummaryNode, ModuleNameWithIsBoot -> Maybe SummaryNode)
 moduleGraphNodes drop_hs_boot_nodes summaries =
   (graphFromEdgedVerticesUniq nodes, lookup_node)
   where
     numbered_summaries = zip summaries [1..]
 
-    lookup_node :: IsBootInterface -> ModuleName -> Maybe SummaryNode
-    lookup_node hs_src mod = Map.lookup
-      (GWIB { gwib_mod = mod, gwib_isBoot = hs_src })
-      node_map
+    lookup_node :: ModuleNameWithIsBoot -> Maybe SummaryNode
+    lookup_node mnwib = Map.lookup mnwib node_map
 
-    lookup_key :: IsBootInterface -> ModuleName -> Maybe Int
-    lookup_key hs_src mod = fmap summaryNodeKey (lookup_node hs_src mod)
+    lookup_key :: ModuleNameWithIsBoot -> Maybe Int
+    lookup_key = fmap summaryNodeKey . lookup_node
 
     node_map :: NodeMap SummaryNode
     node_map = Map.fromList [ ( GWIB
@@ -1998,37 +2023,19 @@ moduleGraphNodes drop_hs_boot_nodes summaries =
                               , node
                               )
                             | node <- nodes
-                            , let s = summaryNodeSummary node ]
+                            , let s = summaryNodeSummary node
+                            ]
 
     -- We use integers as the keys for the SCC algorithm
     nodes :: [SummaryNode]
-    nodes = [ DigraphNode s key out_keys
+    nodes = [ DigraphNode s key $ out_edge_keys $ unfilteredEdges drop_hs_boot_nodes s
             | (s, key) <- numbered_summaries
              -- Drop the hi-boot ones if told to do so
             , not (isBootSummary s == IsBoot && drop_hs_boot_nodes)
-            , let out_keys = out_edge_keys hs_boot_key (map unLoc (ms_home_srcimps s)) ++
-                             out_edge_keys NotBoot     (map unLoc (ms_home_imps s)) ++
-                             (-- see [boot-edges] below
-                              if drop_hs_boot_nodes || ms_hsc_src s == HsBootFile
-                              then []
-                              else case lookup_key IsBoot (ms_mod_name s) of
-                                    Nothing -> []
-                                    Just k  -> [k]) ]
-
-    -- [boot-edges] if this is a .hs and there is an equivalent
-    -- .hs-boot, add a link from the former to the latter.  This
-    -- has the effect of detecting bogus cases where the .hs-boot
-    -- depends on the .hs, by introducing a cycle.  Additionally,
-    -- it ensures that we will always process the .hs-boot before
-    -- the .hs, and so the HomePackageTable will always have the
-    -- most up to date information.
-
-    -- Drop hs-boot nodes by using HsSrcFile as the key
-    hs_boot_key | drop_hs_boot_nodes = NotBoot -- is regular mod or signature
-                | otherwise          = IsBoot
+            ]
 
-    out_edge_keys :: IsBootInterface -> [ModuleName] -> [Int]
-    out_edge_keys hi_boot ms = mapMaybe (lookup_key hi_boot) ms
+    out_edge_keys :: [ModuleNameWithIsBoot] -> [Int]
+    out_edge_keys = mapMaybe lookup_key
         -- If we want keep_hi_boot_nodes, then we do lookup_key with
         -- IsBoot; else False
 


=====================================
compiler/GHC/Unit/Module.hs
=====================================
@@ -47,8 +47,6 @@ module GHC.Unit.Module
     , installedModuleEq
 
       -- * Boot modules
-    , ModuleNameWithIsBoot
-    , ModuleWithIsBoot
     , GenWithIsBoot(..)
     ) where
 



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/97684237b6423a0140abb2112b3d11ed4e7b7e73

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/97684237b6423a0140abb2112b3d11ed4e7b7e73
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20200626/abc6d601/attachment-0001.html>


More information about the ghc-commits mailing list