[Git][ghc/ghc][wip/mpickering/get-link-deps] 5 commits: stable sort

Matthew Pickering (@mpickering) gitlab at gitlab.haskell.org
Fri Jan 3 17:52:33 UTC 2025



Matthew Pickering pushed to branch wip/mpickering/get-link-deps at Glasgow Haskell Compiler / GHC


Commits:
4c9a552e by Matthew Pickering at 2025-01-03T12:52:52+00:00
stable sort

- - - - -
60579bfd by Matthew Pickering at 2025-01-03T12:52:57+00:00
Revert "stable sort"

This reverts commit 4c9a552e74a0f71457ade17f1074d6c87d5b6d7c.

- - - - -
74376306 by Matthew Pickering at 2025-01-03T14:34:34+00:00
Revert "WIP: Use a stable scc algorithm"

This reverts commit c1f36074deb6f3b1508aa9ac92d464dd20624c82.

- - - - -
a2d7b093 by Matthew Pickering at 2025-01-03T17:22:39+00:00
fixes

- - - - -
d29af41a by Matthew Pickering at 2025-01-03T17:51:32+00:00
Rework module structure

- - - - -


10 changed files:

- compiler/GHC/Data/Graph/Directed/Internal.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModIface.hs
- + compiler/GHC/Unit/Module/ModNodeKey.hs
- compiler/ghc.cabal.in
- testsuite/tests/count-deps/CountDepsAst.stdout


Changes:

=====================================
compiler/GHC/Data/Graph/Directed/Internal.hs
=====================================
@@ -7,10 +7,6 @@ import Data.Array
 import qualified Data.Graph as G
 import Data.Graph ( Vertex, SCC(..) ) -- Used in the underlying representation
 import Data.Tree
-import Data.Array.ST.Safe (STUArray)
-import Control.Monad.ST
-import Data.Array.ST.Safe (newArray, readArray, writeArray)
-import Data.List (sort)
 
 data Graph node = Graph {
     gr_int_graph      :: IntGraph,
@@ -73,7 +69,7 @@ reachable g vs = preorderF (G.dfs g vs)
 scc :: IntGraph -> [SCC Vertex]
 scc graph = map decode forest
   where
-    forest = {-# SCC "Digraph.scc" #-} scc2 graph
+    forest = {-# SCC "Digraph.scc" #-} G.scc graph
 
     decode (Node v []) | mentions_itself v = CyclicSCC [v]
                        | otherwise         = AcyclicSCC v
@@ -81,68 +77,3 @@ scc graph = map decode forest
       where dec (Node v ts) vs = v : foldr dec vs ts
     mentions_itself v = v `elem` (graph ! v)
 
-
-
-newtype SetM s a = SetM { runSetM :: STUArray s Vertex Bool -> ST s a }
-
-instance Monad (SetM s) where
-    return = pure
-    {-# INLINE return #-}
-    SetM v >>= f = SetM $ \s -> do { x <- v s; runSetM (f x) s }
-    {-# INLINE (>>=) #-}
-
-instance Functor (SetM s) where
-    f `fmap` SetM v = SetM $ \s -> f `fmap` v s
-    {-# INLINE fmap #-}
-
-instance Applicative (SetM s) where
-    pure x = SetM $ const (return x)
-    {-# INLINE pure #-}
-    SetM f <*> SetM v = SetM $ \s -> f s >>= (`fmap` v s)
-    -- We could also use the following definition
-    --   SetM f <*> SetM v = SetM $ \s -> f s <*> v s
-    -- but Applicative (ST s) instance is present only in GHC 7.2+
-    {-# INLINE (<*>) #-}
-
-run          :: G.Bounds -> (forall s. SetM s a) -> a
-run bnds act  = runST (newArray bnds False >>= runSetM act)
-
-contains     :: Vertex -> SetM s Bool
-contains v    = SetM $ \ m -> readArray m v
-
-include      :: Vertex -> SetM s ()
-include v     = SetM $ \ m -> writeArray m v True
-
-scc2 :: G.Graph -> [Tree Vertex]
-scc2 g = dfs g (reverse (postOrd (G.transposeG g)))
-
-postorder :: Tree a -> [a] -> [a]
-postorder (Node a ts) = postorderF ts . (a :)
-
-postorderF   :: [Tree a] -> [a] -> [a]
-postorderF ts = foldr (.) id $ map postorder ts
-
-postOrd :: G.Graph -> [Vertex]
-postOrd g = postorderF (dff g) []
-
-dff          :: G.Graph -> [Tree Vertex]
-dff g         = dfs g (G.vertices g)
-
-
--- This dfs provides stability under transposition.
-dfs :: G.Graph -> [Vertex] -> [Tree Vertex]
-dfs g vs0 = run (bounds g) $ go vs0
-  where
-    go :: [Vertex] -> SetM s [Tree Vertex]
-    go [] = pure []
-    go (k: is')  = do
-      visited <- contains k
-      if visited
-        then go is'
-        else do
-          include k
-          as <- go (sort (g!k))
-          bs <- go is'
-          pure $ Node k as : bs
-
-


=====================================
compiler/GHC/Driver/Make.hs
=====================================
@@ -125,7 +125,8 @@ import qualified Control.Monad.Catch as MC
 import Data.IORef
 import Data.Maybe
 import Data.Time
-import Data.List (sortOn, unfoldr)
+import Data.Function
+import Data.List (sortOn, unfoldr, sortBy)
 import Data.Bifunctor (first)
 import System.Directory
 import System.FilePath
@@ -1491,7 +1492,24 @@ topSortModuleGraph
 topSortModuleGraph drop_hs_boot_nodes module_graph mb_root_mod =
     -- stronglyConnCompG flips the original order, so if we reverse
     -- the summaries we get a stable topological sort.
-  topSortModules drop_hs_boot_nodes (reverse $ mgModSummaries' module_graph) mb_root_mod
+  topSortModules drop_hs_boot_nodes (sortBy (cmpModuleGraphNodes `on` mkNodeKey) $ mgModSummaries' module_graph) mb_root_mod
+
+
+  where
+    -- In order to get the "right" ordering
+    --    Module nodes must be in reverse lexigraphic order.
+    --    All modules nodes must appear before package nodes or link nodes.
+    --
+    -- Given the current implementation of scc, the result is in
+    -- The order is sensitive to the internal implementation in Data.Graph,
+    -- if it changes in future then this ordering will need to be modified.
+    cmpModuleGraphNodes (NodeKey_Module k1) (NodeKey_Module k2) = compare k2 k1
+    cmpModuleGraphNodes (NodeKey_Link uid1)   (NodeKey_Link uid2) = compare uid2 uid1
+    cmpModuleGraphNodes (NodeKey_Link {}) _                     = LT
+    cmpModuleGraphNodes _                   (NodeKey_Link {})   = GT
+    cmpModuleGraphNodes (NodeKey_Module {}) _                   = LT
+    cmpModuleGraphNodes _                   (NodeKey_Module {}) = GT
+    cmpModuleGraphNodes n1                n2                    = compare n2 n1
 
 topSortModules :: Bool -> [ModuleGraphNode] -> Maybe HomeUnitModule -> [SCC ModuleGraphNode]
 topSortModules drop_hs_boot_nodes summaries mb_root_mod
@@ -1723,7 +1741,10 @@ downsweep_imports hsc_env old_summaries excl_mods allow_dup_roots (root_errs, ro
                case mb_s of
                    NotThere -> loopImports ss done summarised
                    External uid -> do
-                    let done' = loopUnit done [uid]
+                    -- Pass an updated hsc_env to loopUnit, as each unit might
+                    -- have a different visible package database.
+                    let hsc_env' = hscSetActiveHomeUnit home_unit hsc_env
+                    let done' = loopUnit hsc_env' done [uid]
                     (other_deps, done'', summarised') <- loopImports ss done' summarised
                     return (NodeKey_ExternalUnit uid : other_deps, done'', summarised')
                    FoundInstantiation iud -> do
@@ -1743,14 +1764,14 @@ downsweep_imports hsc_env old_summaries excl_mods allow_dup_roots (root_errs, ro
             GWIB { gwib_mod = L loc mod, gwib_isBoot = is_boot } = gwib
             wanted_mod = L loc mod
 
-        loopUnit :: Map.Map NodeKey ModuleGraphNode -> [UnitId] -> Map.Map NodeKey ModuleGraphNode
-        loopUnit cache [] = cache
-        loopUnit cache (u:uxs) = do
+        loopUnit :: HscEnv -> Map.Map NodeKey ModuleGraphNode -> [UnitId] -> Map.Map NodeKey ModuleGraphNode
+        loopUnit _ cache [] = cache
+        loopUnit lcl_hsc_env cache (u:uxs) = do
            let nk = (NodeKey_ExternalUnit u)
            case Map.lookup nk cache of
-             Just {} -> loopUnit cache uxs
-             Nothing -> case unitDepends <$> lookupUnitId (hsc_units hsc_env) u of
-                         Just us -> loopUnit (loopUnit (Map.insert nk (PackageNode us u) cache) us) uxs
+             Just {} -> loopUnit lcl_hsc_env cache uxs
+             Nothing -> case unitDepends <$> lookupUnitId (hsc_units lcl_hsc_env) u of
+                         Just us -> loopUnit lcl_hsc_env (loopUnit lcl_hsc_env (Map.insert nk (PackageNode us u) cache) us) uxs
                          Nothing -> pprPanic "loopUnit" (text "Malformed package database, missing " <+> ppr u)
 
 getRootSummary ::


=====================================
compiler/GHC/Iface/Load.hs
=====================================
@@ -25,7 +25,7 @@ module GHC.Iface.Load (
         -- IfM functions
         loadInterface,
         loadSysInterface, loadUserInterface, loadPluginInterface,
-        loadHomePackageInterfacesBelow,
+        loadExternalGraphBelow,
         findAndReadIface, readIface, writeIface,
         flagsToIfCompression,
         moduleFreeHolesPrecise,
@@ -423,44 +423,96 @@ loadInterfaceWithException doc mod_name where_from
 -- For convenience, reads the module graph out of the EPS after having loaded
 -- all the modules and returns it. It would be harder to get the updated module
 -- graph in 'getLinkDeps' another way.
-loadHomePackageInterfacesBelow :: (Module -> SDoc) -> Maybe HomeUnit {-^ The current home unit -}
-                               -> [Module] -> IfM lcl ()
-loadHomePackageInterfacesBelow _ Nothing _ = panic "loadHomePackageInterfacesBelow: No home unit"
-loadHomePackageInterfacesBelow msg (Just home_unit) mods = do
+loadExternalGraphBelow :: (Module -> SDoc) -> Maybe HomeUnit {-^ The current home unit -}
+                               -> Set.Set ExternalKey -> [Module] -> IfM lcl (Set.Set ExternalKey)
+loadExternalGraphBelow _ Nothing _ _ = panic "loadHomePackageInterfacesBelow: No home unit"
+loadExternalGraphBelow msg (Just home_unit) init_loaded mods =
+  foldM (loadExternalGraphModule msg home_unit) init_loaded mods
+
+loadExternalGraphModule :: (Module -> SDoc) -> HomeUnit
+                         -> Set.Set ExternalKey -> Module -> IfM lcl (Set.Set ExternalKey)
+loadExternalGraphModule msg home_unit init_loaded mod
+  | homeUnitId home_unit /= moduleUnitId mod = do
+      loadExternalPackageBelow init_loaded (moduleUnitId mod)
+  | otherwise =  do
+
+      let key = ExternalModuleKey $ ModNodeKeyWithUid (GWIB (moduleName mod) NotBoot) (moduleUnitId mod)
+      let new_cache = Set.insert key init_loaded
+      graph <- eps_module_graph <$> getEps
+
+      if (not (isFullyLoadedModule key graph || Set.member key init_loaded))
+        then actuallyLoadExternalGraphModule msg home_unit new_cache key mod
+        else
+          return init_loaded
+
+actuallyLoadExternalGraphModule
+  :: (Module -> SDoc)
+  -> HomeUnit
+  -> Set.Set ExternalKey
+  -> ExternalKey
+  -> Module
+  -> IOEnv (Env IfGblEnv lcl) (Set.Set ExternalKey)
+actuallyLoadExternalGraphModule  msg home_unit new_cache key mod = do
   dflags <- getDynFlags
   let ctx = initSDocContext dflags defaultUserStyle
+  iface <- withIfaceErr ctx $
+    loadInterface (msg mod) mod (ImportByUser NotBoot)
+
+  -- RM:TODO: THINGS WE ARE NOT DOING
+  --
+  -- The ModIface contains the transitive closure of the module dependencies
+  -- within the current package, *except* for boot modules: if we encounter
+  -- a boot module, we have to find its real interface and discover the
+  -- dependencies of that.  Hence we need to traverse the dependency
+  -- tree recursively.  See bug #936, testcase ghci/prog007.
+
+  let deps = mi_deps iface
+      mod_deps = dep_direct_mods deps
+      pkg_deps = dep_direct_pkgs deps
+
+  -- Load all direct dependencies that are in the home package
+  cache_mods <- loadExternalGraphBelow msg (Just home_unit) new_cache
+    $ map (\(uid, GWIB mn _) -> mkModule (RealUnit (Definite uid)) mn)
+    $ Set.toList mod_deps
+
+  cache_pkgs <- foldM loadExternalPackageBelow cache_mods (Set.toList pkg_deps)
+
+  registerFullyLoaded key
+  return cache_pkgs
+
+registerFullyLoaded :: ExternalKey -> IfM lcl ()
+registerFullyLoaded key = do
+    -- Update the external graph with this module being fully loaded.
+    logger <- getLogger
+    liftIO $ trace_if logger (text "Fully loaded:" <+> ppr key)
+    updateEps_ $ \eps ->
+      eps{eps_module_graph = setFullyLoadedModule key (eps_module_graph eps)}
 
-  forM_ mods $ \mod -> do
-
+loadExternalPackageBelow :: Set.Set ExternalKey -> UnitId ->  IfM lcl (Set.Set ExternalKey)
+loadExternalPackageBelow cache uid = do
     graph <- eps_module_graph <$> getEps
-    let key = ExternalModuleKey $ ModNodeKeyWithUid (GWIB (moduleName mod) NotBoot) (moduleUnitId mod)
-
-    if isFullyLoadedModule key graph
-      then return ()
-      else do
-        iface <- withIfaceErr ctx $
-          loadInterface (msg mod) mod (ImportByUser NotBoot)
+    us    <- hsc_units <$> getTopEnv
+    let key = ExternalPackageKey uid
+    let cache' = Set.insert key cache
+    if not (isFullyLoadedModule key graph || Set.member key cache)
+      then do
+        case unitDepends <$> lookupUnitId us uid of
+          Just dep_uids -> do
+            loadPackageIntoEPSGraph uid dep_uids
+            final_cache <- foldM loadExternalPackageBelow cache' dep_uids
+            registerFullyLoaded key
+            return final_cache
+          Nothing -> pprPanic "loadExternalPackagesBelow: missing" (ppr uid)
+      else
+        return cache
 
-        -- RM:TODO: THINGS WE ARE NOT DOING
-        --
-        -- The ModIface contains the transitive closure of the module dependencies
-        -- within the current package, *except* for boot modules: if we encounter
-        -- a boot module, we have to find its real interface and discover the
-        -- dependencies of that.  Hence we need to traverse the dependency
-        -- tree recursively.  See bug #936, testcase ghci/prog007.
 
-        let deps = mi_deps iface
-            mod_deps = dep_direct_mods deps
 
-        -- Load all direct dependencies that are in the home package
-        loadHomePackageInterfacesBelow msg (Just home_unit)
-          $ map (\(uid, GWIB mn _) -> mkModule (RealUnit (Definite uid)) mn)
-          $ filter ((==) (homeUnitId home_unit) . fst)
-          $ Set.toList mod_deps
+loadPackageIntoEPSGraph :: UnitId -> [UnitId] -> IfM lcl ()
+loadPackageIntoEPSGraph uid dep_uids =
+  updateEps_ $ \eps ->
+    eps { eps_module_graph = extendExternalModuleGraph (NodeExternalPackage uid (Set.fromList dep_uids)) (eps_module_graph eps) }
 
-        -- Update the external graph with this module being fully loaded.
-        updateEps_ $ \eps ->
-          eps{eps_module_graph = setFullyLoadedModule key (eps_module_graph eps)}
 
 ------------------
 loadInterface :: SDoc -> Module -> WhereFrom
@@ -571,24 +623,13 @@ loadInterface doc_str mod from
         ; purged_hsc_env <- getTopEnv
 
         ; let direct_deps = map (uncurry (flip ModNodeKeyWithUid)) $ (Set.toList (dep_direct_mods $ mi_deps iface))
-        ; let direct_pkg_deps = dep_direct_pkgs $ mi_deps iface
+        ; let direct_pkg_deps = Set.toList $ dep_direct_pkgs $ mi_deps iface
         ; let !module_graph_key = -- pprTrace "module_graph_on_load" (ppr (eps_module_graph eps)) $
                 if moduleUnitId mod `elem` hsc_all_home_unit_ids hsc_env
                                     --- ^ home unit mods in eps can only happen in oneshot mode
-                  then Just $ NodeHomePackage (miKey iface) (map ExternalModuleKey direct_deps)
+                  then Just $ NodeHomePackage (miKey iface) (map ExternalModuleKey direct_deps
+                                                            ++ map ExternalPackageKey direct_pkg_deps)
                   else Nothing
-        ; let !module_graph_pkg_key =
-                -- ROMES:TODO: This doesn't work as expected. Insertions on the
-                -- graph don't override previous nodes, they just create new
-                -- ones. We get multiple duplicate nodes with incomplete dependencies each.
-                let pkg_key = toUnitId $ moduleUnit (mi_module iface)
-                 in case emgLookupKey (ExternalPackageKey pkg_key) (eps_module_graph eps) of
-                  Nothing -> NodeExternalPackage pkg_key direct_pkg_deps
-                  Just pkg_node -> case pkg_node of
-                    NodeHomePackage{} -> panic "ExternalPackageKey lookup should never return a NodeHomePackage node"
-                    NodeExternalPackage _ deps_uids ->
-                      NodeExternalPackage pkg_key (deps_uids `Set.union` direct_pkg_deps)
-
 
         ; let final_iface = iface
                                & set_mi_decls     (panic "No mi_decls in PIT")
@@ -634,8 +675,7 @@ loadInterface doc_str mod from
                     let eps_graph'  = case module_graph_key of
                                        Just k -> extendExternalModuleGraph k (eps_module_graph eps)
                                        Nothing -> eps_module_graph eps
-                        eps_graph'' = extendExternalModuleGraph module_graph_pkg_key eps_graph'
-                     in eps_graph'',
+                     in eps_graph',
                   eps_complete_matches
                                    = eps_complete_matches eps ++ new_eps_complete_matches,
                   eps_inst_env     = extendInstEnvList (eps_inst_env eps)


=====================================
compiler/GHC/Linker/Deps.hs
=====================================
@@ -233,10 +233,12 @@ get_reachable_nodes opts mods
         | otherwise
         = return Nothing
 
-    go (ExternalModuleKey . mkModuleNk) emgNodeKey (emgReachableMany emg) (map emgProject) get_mod_info_eps
-    --romes:todo:^ do we need to make sure we only get non-boot files out of
-    --this. perhaps as easy as filtering them out by ModNodeKeyWithUid with is
-    --boot information?
+      get_mod_key m
+        | moduleUnitId m == homeUnitId (ue_unsafeHomeUnit unit_env)
+        = ExternalModuleKey (mkModuleNk m)
+        | otherwise = ExternalPackageKey (moduleUnitId m)
+
+    go get_mod_key emgNodeKey (emgReachableMany emg) (map emgProject) get_mod_info_eps
 
   -- Reachability on 'ModuleGraph' (for --make mode)
   | otherwise


=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -610,7 +610,7 @@ initLinkDepsOpts hsc_env = opts
     ldLoadHomeIfacesBelow msg hu mods
       = do
         initIfaceCheck (text "loader") hsc_env
-          $ loadHomePackageInterfacesBelow msg hu mods
+          $ void $ loadExternalGraphBelow msg hu Set.empty mods
         -- Read the EPS only after `loadHomePackageInterfacesBelow`
         hscEPS hsc_env
 


=====================================
compiler/GHC/Unit/Module/Graph.hs
=====================================
@@ -87,6 +87,7 @@ module GHC.Unit.Module.Graph
    , ModNodeKey
    , ModNodeKeyWithUid(..)
    , msKey
+   , miKey
 
     -- ** Internal node representation
     --
@@ -116,6 +117,7 @@ import GHC.Types.SourceFile ( hscSourceString )
 import GHC.Unit.Module.ModSummary
 import GHC.Unit.Types
 import GHC.Utils.Outputable
+import GHC.Unit.Module.ModIface
 import GHC.Utils.Misc ( partitionWith )
 
 import System.FilePath
@@ -124,6 +126,7 @@ import GHC.Types.Unique.DSet
 import qualified Data.Set as Set
 import Data.Set (Set)
 import GHC.Unit.Module
+import GHC.Unit.Module.ModNodeKey
 import GHC.Linker.Static.Utils
 
 import Data.Bifunctor
@@ -480,16 +483,14 @@ nodeKeyModName :: NodeKey -> Maybe ModuleName
 nodeKeyModName (NodeKey_Module mk) = Just (gwib_mod $ mnkModuleName mk)
 nodeKeyModName _ = Nothing
 
-type ModNodeKey = ModuleNameWithIsBoot
-data ModNodeKeyWithUid = ModNodeKeyWithUid { mnkModuleName :: !ModuleNameWithIsBoot
-                                           , mnkUnitId     :: !UnitId } deriving (Eq, Ord)
-
-instance Outputable ModNodeKeyWithUid where
-  ppr (ModNodeKeyWithUid mnwib uid) = ppr uid <> colon <> ppr mnwib
-
 msKey :: ModSummary -> ModNodeKeyWithUid
 msKey ms = ModNodeKeyWithUid (ms_mnwib ms) (ms_unitid ms)
 
+miKey :: ModIface -> ModNodeKeyWithUid
+miKey hmi = ModNodeKeyWithUid (mi_mnwib hmi) ((toUnitId $ moduleUnit (mi_module hmi)))
+
+type ModNodeKey = ModuleNameWithIsBoot
+
 --------------------------------------------------------------------------------
 -- ** Internal node representation (exposed)
 --------------------------------------------------------------------------------


=====================================
compiler/GHC/Unit/Module/ModIface.hs
=====================================
@@ -82,7 +82,6 @@ module GHC.Unit.Module.ModIface
    , IfaceImport(..)
    , mi_boot
    , mi_fix
-   , miKey
    , mi_semantic_module
    , mi_free_holes
    , mi_mnwib
@@ -126,7 +125,6 @@ import GHC.Utils.Binary
 
 import Control.DeepSeq
 import Control.Exception
-import GHC.Unit.Module.Graph (ModNodeKeyWithUid(..))
 
 
 {- Note [Interface file stages]
@@ -364,8 +362,6 @@ data ModIface_ (phase :: ModIfacePhase)
                 -- See Note [Sharing of ModIface].
      }
 
-miKey :: ModIface -> ModNodeKeyWithUid
-miKey hmi = ModNodeKeyWithUid (mi_mnwib hmi) ((toUnitId $ moduleUnit (mi_module hmi)))
 
 -- Enough information to reconstruct the top level environment for a module
 data IfaceTopEnv


=====================================
compiler/GHC/Unit/Module/ModNodeKey.hs
=====================================
@@ -0,0 +1,12 @@
+module GHC.Unit.Module.ModNodeKey ( ModNodeKeyWithUid(..) ) where
+
+import GHC.Prelude
+import GHC.Utils.Outputable
+import GHC.Unit.Types
+
+data ModNodeKeyWithUid = ModNodeKeyWithUid { mnkModuleName :: !ModuleNameWithIsBoot
+                                           , mnkUnitId     :: !UnitId } deriving (Eq, Ord)
+
+instance Outputable ModNodeKeyWithUid where
+  ppr (ModNodeKeyWithUid mnwib uid) = ppr uid <> colon <> ppr mnwib
+


=====================================
compiler/ghc.cabal.in
=====================================
@@ -941,6 +941,7 @@ Library
         GHC.Unit.Module.Deps
         GHC.Unit.Module.Env
         GHC.Unit.Module.Graph
+        GHC.Unit.Module.ModNodeKey
         GHC.Unit.Module.External.Graph
         GHC.Unit.Module.Imported
         GHC.Unit.Module.Location


=====================================
testsuite/tests/count-deps/CountDepsAst.stdout
=====================================
@@ -199,6 +199,7 @@ GHC.Unit.Module.Env
 GHC.Unit.Module.Imported
 GHC.Unit.Module.Location
 GHC.Unit.Module.ModIface
+GHC.Unit.Module.ModNodeKey
 GHC.Unit.Module.Warnings
 GHC.Unit.Module.WholeCoreBindings
 GHC.Unit.Parser



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c220dfed4f7279e19aec4ae68624590f5e051083...d29af41ae2f249ee403f5307300c83c4a5615607

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c220dfed4f7279e19aec4ae68624590f5e051083...d29af41ae2f249ee403f5307300c83c4a5615607
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/20250103/98a9f1af/attachment-0001.html>


More information about the ghc-commits mailing list