From fb8148e40d9f6487fe26340f21ab2ed2935a01ce Mon Sep 17 00:00:00 2001
From: Matthew Pickering <matthewtpickering@gmail.com>
Date: Wed, 28 Sep 2022 11:55:48 +0100
Subject: [PATCH] Add extra implicit dependencies needed by DeriveLift

Note [ Template Haskell Dependencies ]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Modules in containers use DeriveLift in order to give Lift instances for
the data types. This is problematic for multi-component sessions which involve
loading containers and template-haskell into the same session because

* Lift comes from Language.Haskell.TH.Syntax
* DeriveLift used identifiers from Language.Haskell.TH.Lib.Internal

Therefore the modules add an import on Language.Haskell.TH.Syntax (in order to import Lift)
but no dependency is recorded between the module and
Language.Haskell.TH.Lib.Internal. However, we need to compile the Internal module
before the module in containers as the desugared code for DeriveLift depends on the
combinators defined in this module.

Can we fix this in GHC? How about adding these edges if a module enables DeriveLift?
This option is precluded because -XDeriveLift is included in Haskell2021 so almost
all modules which exhibit a new dependency on `template-haskell` library without
using it. The most straightforward but ugly solution is to explicitly add these
edges to the build graph. Most projects will not encounter this issue because
they will not be compiled in the same session as the `template-haskell` package.

This has already caused a couple of build system issues in GHC, see !9049 for example.
---
 containers/src/Data/Graph.hs             |  2 ++
 containers/src/Data/IntMap/Internal.hs   | 28 ++++++++++++++++++++++++
 containers/src/Data/IntSet/Internal.hs   |  2 ++
 containers/src/Data/Map/Internal.hs      |  2 ++
 containers/src/Data/Sequence/Internal.hs |  2 ++
 containers/src/Data/Set/Internal.hs      |  2 ++
 containers/src/Data/Tree.hs              |  2 ++
 7 files changed, 40 insertions(+)

diff --git a/containers/src/Data/Graph.hs b/containers/src/Data/Graph.hs
index 1957859c..64c33084 100644
--- a/containers/src/Data/Graph.hs
+++ b/containers/src/Data/Graph.hs
@@ -126,6 +126,8 @@ import Data.Semigroup (Semigroup (..))
 import GHC.Generics (Generic, Generic1)
 import Data.Data (Data)
 import Language.Haskell.TH.Syntax (Lift)
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 #endif
 
 -- Make sure we don't use Integer by mistake.
diff --git a/containers/src/Data/IntMap/Internal.hs b/containers/src/Data/IntMap/Internal.hs
index 8b29c6ed..ccd9f2db 100644
--- a/containers/src/Data/IntMap/Internal.hs
+++ b/containers/src/Data/IntMap/Internal.hs
@@ -72,6 +72,32 @@
 -- constructors are ordered by frequency.
 -- On GHC 7.0, reordering constructors from Nil | Tip | Bin to Bin | Tip | Nil
 -- improves the benchmark by circa 10%.
+--
+--
+-- Note [ Template Haskell Dependencies ]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- Modules in containers use DeriveLift in order to give Lift instances for
+-- the data types. This is problematic for multi-component sessions which involve
+-- loading containers and template-haskell into the same session because
+--
+-- * Lift comes from Language.Haskell.TH.Syntax
+-- * DeriveLift used identifiers from Language.Haskell.TH.Lib.Internal
+--
+-- Therefore the modules add an import on Language.Haskell.TH.Syntax (in order to import Lift)
+-- but no dependency is recorded between the module and
+-- Language.Haskell.TH.Lib.Internal. However, we need to compile the Internal module
+-- before the module in containers as the desugared code for DeriveLift depends on the
+-- combinators defined in this module.
+--
+-- Can we fix this in GHC? How about adding these edges if a module enables DeriveLift?
+-- This option is precluded because -XDeriveLift is included in Haskell2021 so almost
+-- all modules which exhibit a new dependency on `template-haskell` library without
+-- using it. The most straightforward but ugly solution is to explicitly add these
+-- edges to the build graph. Most projects will not encounter this issue because
+-- they will not be compiled in the same session as the `template-haskell` package.
+--
+-- This has already caused a couple of build system issues in GHC, see !9049 for example.
 
 module Data.IntMap.Internal (
     -- * Map type
@@ -320,6 +346,8 @@ import GHC.Exts (build)
 import qualified GHC.Exts as GHCExts
 import Text.Read
 import Language.Haskell.TH.Syntax (Lift)
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 #endif
 import qualified Control.Category as Category
 
diff --git a/containers/src/Data/IntSet/Internal.hs b/containers/src/Data/IntSet/Internal.hs
index 1906d2ad..504e5d01 100644
--- a/containers/src/Data/IntSet/Internal.hs
+++ b/containers/src/Data/IntSet/Internal.hs
@@ -215,6 +215,8 @@ import qualified GHC.Exts
 import qualified GHC.Int
 #  endif
 import Language.Haskell.TH.Syntax (Lift)
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 #endif
 
 import qualified Data.Foldable as Foldable
diff --git a/containers/src/Data/Map/Internal.hs b/containers/src/Data/Map/Internal.hs
index c2131572..761a55ed 100644
--- a/containers/src/Data/Map/Internal.hs
+++ b/containers/src/Data/Map/Internal.hs
@@ -398,6 +398,8 @@ import Utils.Containers.Internal.BitUtil (wordSize)
 #if __GLASGOW_HASKELL__
 import GHC.Exts (build, lazy)
 import Language.Haskell.TH.Syntax (Lift)
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 #  ifdef USE_MAGIC_PROXY
 import GHC.Exts (Proxy#, proxy# )
 #  endif
diff --git a/containers/src/Data/Sequence/Internal.hs b/containers/src/Data/Sequence/Internal.hs
index 7b8bf56b..899bcc91 100644
--- a/containers/src/Data/Sequence/Internal.hs
+++ b/containers/src/Data/Sequence/Internal.hs
@@ -226,6 +226,8 @@ import Text.Read (Lexeme(Ident), lexP, parens, prec,
 import Data.Data
 import Data.String (IsString(..))
 import qualified Language.Haskell.TH.Syntax as TH
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 import GHC.Generics (Generic, Generic1)
 #endif
 
diff --git a/containers/src/Data/Set/Internal.hs b/containers/src/Data/Set/Internal.hs
index 15406d8a..5ee9ccbe 100644
--- a/containers/src/Data/Set/Internal.hs
+++ b/containers/src/Data/Set/Internal.hs
@@ -261,6 +261,8 @@ import Text.Read ( readPrec, Read (..), Lexeme (..), parens, prec
                  , lexP, readListPrecDefault )
 import Data.Data
 import Language.Haskell.TH.Syntax (Lift)
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 #endif
 
 
diff --git a/containers/src/Data/Tree.hs b/containers/src/Data/Tree.hs
index 1c9db572..c33b7edb 100644
--- a/containers/src/Data/Tree.hs
+++ b/containers/src/Data/Tree.hs
@@ -63,6 +63,8 @@ import Control.DeepSeq (NFData(rnf))
 import Data.Data (Data)
 import GHC.Generics (Generic, Generic1)
 import Language.Haskell.TH.Syntax (Lift)
+-- See Note [ Template Haskell Dependencies ]
+import Language.Haskell.TH ()
 #endif
 
 import Control.Monad.Zip (MonadZip (..))
-- 
GitLab