[Git][ghc/ghc][wip/fendor/ifacetype-deduplication] WIP: TrieMap for IfaceType

Hannes Siebenhandl (@fendor) gitlab at gitlab.haskell.org
Wed Apr 10 07:24:03 UTC 2024



Hannes Siebenhandl pushed to branch wip/fendor/ifacetype-deduplication at Glasgow Haskell Compiler / GHC


Commits:
600b157a by Matthew Pickering at 2024-04-10T09:23:43+02:00
WIP: TrieMap for IfaceType

- - - - -


8 changed files:

- compiler/GHC/Core/Map/Expr.hs
- compiler/GHC/Data/TrieMap.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Type.hs
- + compiler/GHC/Iface/Type/Map.hs
- compiler/GHC/Stg/CSE.hs
- compiler/GHC/Utils/Binary.hs
- compiler/ghc.cabal.in


Changes:

=====================================
compiler/GHC/Core/Map/Expr.hs
=====================================
@@ -40,6 +40,7 @@ import GHC.Utils.Outputable
 import qualified Data.Map    as Map
 import GHC.Types.Name.Env
 import Control.Monad( (>=>) )
+import GHC.Types.Literal (Literal)
 
 {-
 This module implements TrieMaps over Core related data structures
@@ -128,6 +129,8 @@ instance TrieMap CoreMap where
 -- inside another 'TrieMap', this is the type you want.
 type CoreMapG = GenMap CoreMapX
 
+type LiteralMap = Map.Map Literal
+
 -- | @CoreMapX a@ is the base map from @DeBruijn CoreExpr@ to @a@, but without
 -- the 'GenMap' optimization.
 data CoreMapX a


=====================================
compiler/GHC/Data/TrieMap.hs
=====================================
@@ -13,8 +13,6 @@ module GHC.Data.TrieMap(
    MaybeMap,
    -- * Maps over 'List' values
    ListMap,
-   -- * Maps over 'Literal's
-   LiteralMap,
    -- * 'TrieMap' class
    TrieMap(..), insertTM, deleteTM, foldMapTM, isEmptyTM,
 
@@ -30,7 +28,6 @@ module GHC.Data.TrieMap(
 
 import GHC.Prelude
 
-import GHC.Types.Literal
 import GHC.Types.Unique.DFM
 import GHC.Types.Unique( Uniquable )
 
@@ -39,6 +36,8 @@ import qualified Data.IntMap as IntMap
 import GHC.Utils.Outputable
 import Control.Monad( (>=>) )
 import Data.Kind( Type )
+import Data.Functor.Compose
+import Data.Functor.Product
 
 import qualified Data.Semigroup as S
 
@@ -343,15 +342,87 @@ ftList :: TrieMap m => (a -> Bool) -> ListMap m a -> ListMap m a
 ftList f (LM { lm_nil = mnil, lm_cons = mcons })
   = LM { lm_nil = filterMaybe f mnil, lm_cons = fmap (filterTM f) mcons }
 
-{-
-************************************************************************
-*                                                                      *
-                   Basic maps
-*                                                                      *
-************************************************************************
--}
+{- Composition -}
+
+instance (TrieMap m, TrieMap n) => TrieMap (Compose m n) where
+  type Key (Compose m n) = (Key m, Key n)
+  emptyTM  = Compose emptyTM
+  lookupTM = lkCompose lookupTM lookupTM
+  {-# INLINE lookupTM #-}
+  alterTM  = xtCompose alterTM alterTM
+  {-# INLINE alterTM #-}
+  foldTM   = fdCompose
+  {-# INLINE foldTM #-}
+  filterTM = ftCompose
+  {-# INLINE filterTM #-}
+
+lkCompose :: Monad m => (t1 -> f (g a1) -> m a2) -> (t2 -> a2 -> m b) -> (t1, t2) -> Compose f g a1 -> m b
+lkCompose f g (a, b) (Compose m) = f a m >>= g b
+{-# INLINE lkCompose #-}
+
+xtCompose ::
+          (TrieMap m, TrieMap n)
+          => (forall a  . Key m -> XT a -> m a -> m a)
+          -> (forall a . Key n -> XT a -> n a -> n a)
+          -> Key (Compose m n)
+          -> XT a
+          -> Compose m n a
+          -> Compose m n a
+
+xtCompose f g (a, b) xt (Compose m) = Compose ((f a |>> g b xt) m)
+
+{-# INLINE xtCompose #-}
+
+fdCompose :: (TrieMap m1, TrieMap m2) => (a -> b -> b) -> Compose m1 m2 a -> b -> b
+fdCompose f (Compose m) = foldTM (foldTM f) m
+
+{-# INLINE fdCompose #-}
+
+
+ftCompose :: (TrieMap n, Functor m) => (a -> Bool) -> Compose m n a -> Compose m n a
+ftCompose f (Compose m) = Compose (fmap (filterTM f) m)
+
+{-# INLINE ftCompose #-}
+
+{- Product -}
+instance (TrieMap m, TrieMap n) => TrieMap (Product m n) where
+  type Key (Product m n) = Either (Key m) (Key n)
+  emptyTM  = Pair emptyTM emptyTM
+  lookupTM = lkProduct
+  {-# INLINE lookupTM #-}
+  alterTM  = xtProduct
+  {-# INLINE alterTM #-}
+  foldTM   = fdProduct
+  {-# INLINE foldTM #-}
+  filterTM = ftProduct
+  {-# INLINE filterTM #-}
+
+lkProduct :: (TrieMap m1, TrieMap m2) => Either (Key m1) (Key m2) -> Product m1 m2 b -> Maybe b
+lkProduct k (Pair am bm) =
+  case k of
+    Left a -> lookupTM a am
+    Right b -> lookupTM b bm
+
+{-# INLINE lkProduct #-}
+
+xtProduct :: (TrieMap f, TrieMap g) => Either (Key f) (Key g) -> XT a -> Product f g a -> Product f g a
+xtProduct k xt (Pair am bm) =
+  case k of
+    Left a -> Pair (alterTM a xt am) bm
+    Right b -> Pair am (alterTM b xt bm)
+
+{-# INLINE xtProduct #-}
+
+fdProduct :: (TrieMap f, TrieMap g) => (a -> c -> c) -> Product f g a -> c -> c
+fdProduct f (Pair am bm) = foldTM f am . foldTM f bm
+
+{-# INLINE fdProduct #-}
+
+ftProduct :: (TrieMap f, TrieMap g) => (a -> Bool) -> Product f g a -> Product f g a
+ftProduct f (Pair am bm) = Pair (filterTM f am) (filterTM f bm)
+
+{-# INLINE ftProduct #-}
 
-type LiteralMap  a = Map.Map Literal a
 
 {-
 ************************************************************************


=====================================
compiler/GHC/Iface/Binary.hs
=====================================
@@ -58,6 +58,7 @@ import Data.IORef
 import Control.Monad
 import GHC.Iface.Type (IfaceType, getIfaceType, putIfaceType)
 import System.IO.Unsafe
+import GHC.Iface.Type.Map (IfaceTypeMap)
 
 
 -- ---------------------------------------------------------------------------
@@ -369,7 +370,7 @@ initReadIfaceTypeTable ud = do
 
 initWriteIfaceType :: IO (WriterTable, BinaryWriter IfaceType)
 initWriteIfaceType = do
-  sym_tab <- initGenericSymbolTable
+  sym_tab <- initGenericSymbolTable @IfaceTypeMap
   pure
     ( WriterTable
         { putTable = putGenericSymbolTable sym_tab (lazyPut' putIfaceType)


=====================================
compiler/GHC/Iface/Type.hs
=====================================
@@ -112,6 +112,10 @@ newtype IfLclName = IfLclName
   { getIfLclName :: LexicalFastString
   } deriving (Eq, Ord, Show)
 
+instance Uniquable IfLclName where
+  getUnique = getUnique . ifLclNameFS
+
+
 ifLclNameFS :: IfLclName -> FastString
 ifLclNameFS = getLexicalFastString . getIfLclName
 


=====================================
compiler/GHC/Iface/Type/Map.hs
=====================================
@@ -0,0 +1,180 @@
+{-# LANGUAGE TypeFamilies #-}
+module GHC.Iface.Type.Map where
+
+import GHC.Prelude
+import GHC.Data.TrieMap
+import GHC.Iface.Type
+import qualified Data.Map as Map
+import Data.Functor.Compose
+import GHC.Types.Basic
+import Control.Monad ((>=>))
+import GHC.Types.Unique.DFM
+import Data.Functor.Product
+import GHC.Types.Var (VarBndr(..))
+
+
+newtype IfaceTypeMap a = IfaceTypeMap (IfaceTypeMapG a)
+
+instance Functor IfaceTypeMap where
+  fmap f (IfaceTypeMap m) = IfaceTypeMap (fmap f m)
+
+instance TrieMap IfaceTypeMap where
+  type Key IfaceTypeMap = IfaceType
+
+  emptyTM = IfaceTypeMap emptyTM
+
+  lookupTM k (IfaceTypeMap m) = lookupTM k m
+
+  alterTM k f (IfaceTypeMap m) = IfaceTypeMap (alterTM k f m)
+
+  filterTM f (IfaceTypeMap m) = IfaceTypeMap (filterTM f m)
+
+  foldTM f (IfaceTypeMap m) = foldTM f m
+
+type IfaceTypeMapG = GenMap IfaceTypeMapX
+
+data IfaceTypeMapX a
+  = IFM { ifm_lit :: IfaceLiteralMap a
+        , ifm_var :: UniqDFM IfLclName a
+        , ifm_app :: IfaceTypeMapG (IfaceAppArgsMap a)
+        , ifm_fun_ty :: FunTyFlagMap (IfaceTypeMapG (IfaceTypeMapG (IfaceTypeMapG a)))
+        , ifm_ty_con_app :: IfaceTyConMap (IfaceAppArgsMap a)
+        , ifm_forall_ty :: IfaceForAllBndrMap (IfaceTypeMapG a)
+        , ifm_cast_ty :: IfaceTypeMapG (IfaceCoercionMap a)
+        , ifm_coercion_ty :: IfaceCoercionMap a
+        , ifm_tuple_ty :: TupleSortMap (PromotionFlagMap (IfaceAppArgsMap a))  }
+
+type IfaceLiteralMap = Map.Map IfaceTyLit
+type FunTyFlagMap = Map.Map FunTyFlag
+type IfaceTyConMap = Map.Map IfaceTyCon
+type ForAllTyFlagMap = Map.Map ForAllTyFlag
+type IfaceCoercionMap = Map.Map IfaceCoercion
+type TupleSortMap = Map.Map TupleSort
+type PromotionFlagMap = Map.Map PromotionFlag
+type IfaceForAllBndrMap = Compose IfaceBndrMap ForAllTyFlagMap
+
+type IfaceIdBndrMap = Compose IfaceTypeMapG (Compose (UniqDFM IfLclName) IfaceTypeMapG)
+type IfaceTvBndrMap = Compose (UniqDFM IfLclName) IfaceTypeMapG
+
+type IfaceBndrMap = Product IfaceIdBndrMap IfaceTvBndrMap
+
+
+
+
+type IfaceAppArgsMap a = ListMap (Compose IfaceTypeMapG ForAllTyFlagMap) a
+
+emptyE :: IfaceTypeMapX a
+emptyE = IFM { ifm_lit = emptyTM
+             , ifm_var = emptyTM
+             , ifm_app = emptyTM
+             , ifm_fun_ty = emptyTM
+             , ifm_ty_con_app = emptyTM
+             , ifm_forall_ty = emptyTM
+             , ifm_cast_ty = emptyTM
+             , ifm_coercion_ty = emptyTM
+             , ifm_tuple_ty = emptyTM }
+
+instance Functor IfaceTypeMapX where
+  fmap f  IFM { ifm_lit = ilit
+          , ifm_var = ivar
+          , ifm_app = iapp
+          , ifm_fun_ty = ift
+          , ifm_ty_con_app = itc
+          , ifm_forall_ty = ifal
+          , ifm_cast_ty = icast
+          , ifm_coercion_ty = ico
+          , ifm_tuple_ty = itup }
+
+    = IFM { ifm_lit = fmap f ilit
+          , ifm_var = fmap f ivar
+          , ifm_app = fmap (fmap f) iapp
+          , ifm_fun_ty = fmap (fmap (fmap (fmap f))) ift
+          , ifm_ty_con_app = fmap (fmap f) itc
+          , ifm_forall_ty = fmap (fmap f) ifal
+          , ifm_cast_ty = fmap (fmap f) icast
+          , ifm_coercion_ty = fmap f ico
+          , ifm_tuple_ty = fmap (fmap (fmap f)) itup }
+
+instance TrieMap IfaceTypeMapX where
+  type Key IfaceTypeMapX = IfaceType
+
+  emptyTM = emptyE
+  lookupTM = lkE
+  alterTM = xtE
+  foldTM = fdE
+  filterTM = ftE
+  {-# INLINE lookupTM #-}
+  {-# INLINE alterTM #-}
+
+{-# INLINE ftE #-}
+ftE :: (a -> Bool) -> IfaceTypeMapX a -> IfaceTypeMapX a
+ftE f  IFM { ifm_lit = ilit
+          , ifm_var = ivar
+          , ifm_app = iapp
+          , ifm_fun_ty = ift
+          , ifm_ty_con_app = itc
+          , ifm_forall_ty = ifal
+          , ifm_cast_ty = icast
+          , ifm_coercion_ty = ico
+          , ifm_tuple_ty = itup }
+
+    = IFM { ifm_lit = filterTM f ilit
+          , ifm_var = filterTM f ivar
+          , ifm_app = fmap (filterTM f) iapp
+          , ifm_fun_ty = fmap (fmap (fmap (filterTM f))) ift
+          , ifm_ty_con_app = fmap (filterTM f) itc
+          , ifm_forall_ty = fmap (filterTM f) ifal
+          , ifm_cast_ty = fmap (filterTM f) icast
+          , ifm_coercion_ty = filterTM f ico
+          , ifm_tuple_ty = fmap (fmap (filterTM f)) itup }
+
+{-# INLINE fdE #-}
+fdE :: (a -> b -> b) -> IfaceTypeMapX a -> b -> b
+fdE f  IFM { ifm_lit = ilit
+          , ifm_var = ivar
+          , ifm_app = iapp
+          , ifm_fun_ty = ift
+          , ifm_ty_con_app = itc
+          , ifm_forall_ty = ifal
+          , ifm_cast_ty = icast
+          , ifm_coercion_ty = ico
+          , ifm_tuple_ty = itup }
+  = foldTM f ilit . foldTM f ivar . foldTM (foldTM f) iapp
+  . foldTM (foldTM (foldTM (foldTM f))) ift
+  . foldTM (foldTM f) itc
+  . foldTM (foldTM f) ifal
+  . foldTM (foldTM f) icast
+  . foldTM f ico
+  . foldTM (foldTM (foldTM f)) itup
+
+bndrToKey :: IfaceBndr -> Either (IfaceType, (IfLclName, IfaceType)) IfaceTvBndr
+bndrToKey (IfaceIdBndr (a,b,c)) = Left (a, (b,c))
+bndrToKey (IfaceTvBndr k) = Right k
+
+{-# INLINE lkE #-}
+lkE :: IfaceType -> IfaceTypeMapX a -> Maybe a
+lkE it ifm = go it ifm
+  where
+    go (IfaceFreeTyVar {}) = error "ftv"
+    go (IfaceTyVar var) = ifm_var >.> lookupTM var
+    go (IfaceLitTy l) = ifm_lit >.> lookupTM l
+    go (IfaceAppTy ift args) = ifm_app >.> lkG ift >=> lookupTM (appArgsIfaceTypesForAllTyFlags args)
+    go (IfaceFunTy ft t1 t2 t3) = ifm_fun_ty >.> lookupTM ft >=> lkG t1 >=> lkG t2 >=> lkG t3
+    go (IfaceForAllTy (Bndr a b) t) = ifm_forall_ty >.> lookupTM (bndrToKey a,b) >=> lkG t
+    go (IfaceTyConApp tc args) = ifm_ty_con_app >.> lookupTM tc >=> lookupTM (appArgsIfaceTypesForAllTyFlags args)
+    go (IfaceCastTy ty co) = ifm_cast_ty >.> lkG ty >=> lookupTM co
+    go (IfaceCoercionTy co) = ifm_coercion_ty >.> lookupTM co
+    go (IfaceTupleTy sort prom args) = ifm_tuple_ty >.> lookupTM sort >=> lookupTM prom >=> lookupTM (appArgsIfaceTypesForAllTyFlags args)
+
+{-# INLINE xtE #-}
+xtE :: IfaceType -> XT a -> IfaceTypeMapX a -> IfaceTypeMapX a
+xtE (IfaceFreeTyVar {}) _ _ = error "ftv"
+xtE (IfaceTyVar var) f m = m { ifm_var = ifm_var m |> alterTM var f }
+xtE (IfaceLitTy l) f m = m { ifm_lit = ifm_lit m |> alterTM l f }
+xtE (IfaceAppTy ift args) f m = m { ifm_app = ifm_app m |> xtG ift |>> alterTM (appArgsIfaceTypesForAllTyFlags args) f }
+xtE (IfaceFunTy ft t1 t2 t3) f m = m { ifm_fun_ty = ifm_fun_ty m |> alterTM ft |>> xtG t1 |>> xtG t2 |>> xtG t3 f }
+xtE (IfaceForAllTy (Bndr a b) t) f m = m { ifm_forall_ty = ifm_forall_ty m |> alterTM (bndrToKey a,b) |>> xtG t f }
+xtE (IfaceTyConApp tc args) f m = m { ifm_ty_con_app = ifm_ty_con_app m |> alterTM tc |>> alterTM (appArgsIfaceTypesForAllTyFlags args) f }
+xtE (IfaceCastTy ty co) f m = m { ifm_cast_ty = ifm_cast_ty m |> xtG ty |>> alterTM co f }
+xtE (IfaceCoercionTy co) f m = m { ifm_coercion_ty = ifm_coercion_ty m |> alterTM co f }
+xtE (IfaceTupleTy sort prom args) f m = m { ifm_tuple_ty = ifm_tuple_ty m |> alterTM sort |>> alterTM prom |>> alterTM (appArgsIfaceTypesForAllTyFlags args) f }


=====================================
compiler/GHC/Stg/CSE.hs
=====================================
@@ -109,6 +109,8 @@ import GHC.Core.Map.Expr
 import GHC.Data.TrieMap
 import GHC.Types.Name.Env
 import Control.Monad( (>=>) )
+import qualified Data.Map as Map
+import GHC.Types.Literal ( Literal )
 
 --------------
 -- The Trie --
@@ -122,6 +124,8 @@ data StgArgMap a = SAM
     , sam_lit :: LiteralMap a
     }
 
+type LiteralMap = Map.Map Literal
+
 -- TODO(22292): derive
 instance Functor StgArgMap where
     fmap f SAM { sam_var = varm, sam_lit = litm } = SAM


=====================================
compiler/GHC/Utils/Binary.hs
=====================================
@@ -2,6 +2,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
 
 {-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -136,7 +137,7 @@ import qualified Data.Map.Strict as Map
 import Data.Set                 ( Set )
 import qualified Data.Set as Set
 import Data.Time
-import Data.List (sortOn, unfoldr)
+import Data.List (unfoldr)
 import Data.Typeable
 import System.IO as IO
 import System.IO.Unsafe         ( unsafeInterleaveIO )
@@ -150,6 +151,9 @@ import GHC.ForeignPtr           ( unsafeWithForeignPtr )
 
 import Unsafe.Coerce (unsafeCoerce)
 import Data.Coerce
+import GHC.Data.TrieMap
+
+
 
 type BinArray = ForeignPtr Word8
 
@@ -1348,44 +1352,47 @@ data WriterTable = WriterTable
 -- binary serialisation and deserialisation.
 -- ----------------------------------------------------------------------------
 
-data GenericSymbolTable a = GenericSymbolTable
+data GenericSymbolTable m = GenericSymbolTable
   { gen_symtab_next :: !FastMutInt
   -- ^ The next index to use
-  , gen_symtab_map  :: !(IORef (Map.Map a Int))
+  , gen_symtab_map  :: !(IORef (m Int))
   -- ^ Given a symbol, find the symbol
+  , gen_symtab_to_write :: !(IORef [Key m])
+  -- ^ Reversed list of values to write into the buffer
   }
 
-initGenericSymbolTable :: IO (GenericSymbolTable a)
+initGenericSymbolTable :: TrieMap m => IO (GenericSymbolTable m)
 initGenericSymbolTable = do
   symtab_next <- newFastMutInt 0
-  symtab_map <- newIORef Map.empty
+  symtab_map <- newIORef emptyTM
+  symtab_todo <- newIORef []
   pure $ GenericSymbolTable
         { gen_symtab_next = symtab_next
         , gen_symtab_map  = symtab_map
+        , gen_symtab_to_write = symtab_todo
         }
 
-putGenericSymbolTable :: forall a. GenericSymbolTable a -> (WriteBinHandle -> a -> IO ()) -> WriteBinHandle -> IO Int
+{-# INLINE putGenericSymbolTable #-}
+putGenericSymbolTable :: forall m. (TrieMap m) => GenericSymbolTable m -> (WriteBinHandle -> Key m -> IO ()) -> WriteBinHandle -> IO Int
 putGenericSymbolTable gen_sym_tab serialiser bh = do
   putGenericSymbolTable bh
   where
-    symtab_map = gen_symtab_map gen_sym_tab
     symtab_next = gen_symtab_next gen_sym_tab
+    symtab_to_write = gen_symtab_to_write gen_sym_tab
     putGenericSymbolTable :: HasCallStack => WriteBinHandle -> IO Int
     putGenericSymbolTable bh  = do
-      let loop bound = do
-            d <- readIORef symtab_map
-            table_count <- readFastMutInt symtab_next
-            let vs = sortOn fst [(b, a) | (a,b) <- Map.toList  d, b >= bound]
+      let loop = do
+            vs <- atomicModifyIORef' symtab_to_write (\a -> ([], a))
             case vs of
-              [] -> return table_count
+              [] -> readFastMutInt symtab_next
               todo -> do
-                mapM_ (\n -> serialiser bh n) (map snd todo)
-                loop table_count
+                mapM_ (\n -> serialiser bh n) (reverse todo)
+                loop
       snd <$>
         (forwardPut bh (const $ readFastMutInt symtab_next >>= put_ bh) $
-          loop 0)
+          loop)
 
-getGenericSymbolTable :: forall a. (ReadBinHandle -> IO a) -> ReadBinHandle -> IO (SymbolTable a)
+getGenericSymbolTable :: forall a . (ReadBinHandle -> IO a) -> ReadBinHandle -> IO (SymbolTable a)
 getGenericSymbolTable deserialiser bh = do
   sz <- forwardGet bh (get bh) :: IO Int
   mut_arr <- newArray_ (0, sz-1) :: IO (IOArray Int a)
@@ -1397,19 +1404,22 @@ getGenericSymbolTable deserialiser bh = do
     writeArray mut_arr i f
   unsafeFreeze mut_arr
 
-putGenericSymTab :: (Ord a, Binary a) => GenericSymbolTable a -> WriteBinHandle -> a -> IO ()
+{-# INLINE putGenericSymTab #-}
+putGenericSymTab :: (TrieMap m) => GenericSymbolTable m -> WriteBinHandle -> Key m -> IO ()
 putGenericSymTab GenericSymbolTable{
                gen_symtab_map = symtab_map_ref,
-               gen_symtab_next = symtab_next }
+               gen_symtab_next = symtab_next,
+               gen_symtab_to_write = symtab_todo }
         bh val = do
   symtab_map <- readIORef symtab_map_ref
-  case Map.lookup val symtab_map of
+  case lookupTM val symtab_map of
     Just off -> put_ bh (fromIntegral off :: Word32)
     Nothing -> do
       off <- readFastMutInt symtab_next
       writeFastMutInt symtab_next (off+1)
       writeIORef symtab_map_ref
-          $! Map.insert val off symtab_map
+          $! insertTM val off symtab_map
+      atomicModifyIORef symtab_todo (\todo -> (val : todo, ()))
       put_ bh (fromIntegral off :: Word32)
 
 getGenericSymtab :: Binary a => SymbolTable a -> ReadBinHandle -> IO a


=====================================
compiler/ghc.cabal.in
=====================================
@@ -579,6 +579,7 @@ Library
         GHC.Iface.Tidy.StaticPtrTable
         GHC.IfaceToCore
         GHC.Iface.Type
+        GHC.Iface.Type.Map
         GHC.JS.Ident
         GHC.JS.Make
         GHC.JS.Optimizer



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/600b157a0bc6f9063fbed88fe3b65ed2d04a55cf

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/600b157a0bc6f9063fbed88fe3b65ed2d04a55cf
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/20240410/41d63c84/attachment-0001.html>


More information about the ghc-commits mailing list