From a05bd2872d01a41991fdb35f9431e0c54efaa8fb Mon Sep 17 00:00:00 2001
From: Cheng Shao <terrorjack@type.dance>
Date: Thu, 13 Feb 2025 23:43:10 +0000
Subject: [PATCH] compiler: avoid overwriting existing writers in putWithTables

This patch makes `putWithTables` avoid overwriting all existing
UserData writers in the handle. This is crucial for GHC API users that
use putWithUserData/getWithUserData for serialization logic that
involve Names.

(cherry picked from commit c331eebf575221ed8c67ca232bac4ae047b794a3)
---
 compiler/GHC/Iface/Binary.hs | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/compiler/GHC/Iface/Binary.hs b/compiler/GHC/Iface/Binary.hs
index 94ebbad34c3..25739f77fc5 100644
--- a/compiler/GHC/Iface/Binary.hs
+++ b/compiler/GHC/Iface/Binary.hs
@@ -43,7 +43,6 @@ import GHC.Types.Unique.FM
 import GHC.Utils.Panic
 import GHC.Utils.Binary as Binary
 import GHC.Data.FastMutInt
-import GHC.Data.FastString (FastString)
 import GHC.Types.Unique
 import GHC.Utils.Outputable
 import GHC.Types.Name.Cache
@@ -321,18 +320,21 @@ putWithTables compressionLevel bh' put_payload = do
   (ifaceType_wt, ifaceTypeWriter) <- initWriteIfaceType compressionLevel
 
   -- Initialise the 'WriterUserData'.
-  let writerUserData = mkWriterUserData
-        [ mkSomeBinaryWriter @FastString fsWriter
-        , mkSomeBinaryWriter @Name nameWriter
-        -- We sometimes serialise binding and non-binding names differently, but
-        -- not during 'ModIface' serialisation. Here, we serialise both to the same
-        -- deduplication table.
-        --
-        -- See Note [Binary UserData]
-        , mkSomeBinaryWriter @BindingName  $ mkWriter (\bh name -> putEntry nameWriter bh (getBindingName name))
-        , mkSomeBinaryWriter @IfaceType ifaceTypeWriter
-        ]
-  let bh = setWriterUserData bh' writerUserData
+  --
+  -- Similar to how 'getTables' calls 'addReaderToUserData', here we
+  -- call 'addWriterToUserData' instead of 'setWriterUserData', to
+  -- avoid overwriting existing writers of other types in bh'.
+  let bh =
+        addWriterToUserData fsWriter
+          $ addWriterToUserData nameWriter
+          -- We sometimes serialise binding and non-binding names differently, but
+          -- not during 'ModIface' serialisation. Here, we serialise both to the same
+          -- deduplication table.
+          --
+          -- See Note [Binary UserData]
+          $ addWriterToUserData
+            (mkWriter $ \bh name -> putEntry nameWriter bh $ getBindingName name)
+          $ addWriterToUserData ifaceTypeWriter bh'
 
   ([fs_count, name_count, ifacetype_count] , r) <-
     -- The order of these entries matters!
-- 
GitLab