diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for dependent-sum-template
 
+## 0.2.0.0 - 2023-08-01
+
+* Recover compatibility with template-haskell 2.18, which was lost in 0.1.2.0
+* deriveGShow will generate code that uses Show instances for every argument to a constructor, apart from those of the type that it is generating an instance for.
+* Drop support for GHC 9.2 and 9.4 due to [a bug in reifyInstances](https://gitlab.haskell.org/ghc/ghc/-/issues/23743)
+
 ## 0.1.2.0 - 2023-07-11
 
 * Rework a lot of the logic using th-abstraction to get structural information about data types and to
diff --git a/dependent-sum-template.cabal b/dependent-sum-template.cabal
--- a/dependent-sum-template.cabal
+++ b/dependent-sum-template.cabal
@@ -1,5 +1,5 @@
 name:                   dependent-sum-template
-version:                0.1.2.0
+version:                0.2.0.0
 stability:              experimental
 
 cabal-version:          >= 1.10
@@ -14,12 +14,12 @@
 synopsis:               Template Haskell code to generate instances of classes in some package
 description:            Template Haskell code to generate instances of classes in some package, such as 'GEq' and 'GCompare'.
 
-tested-with:            GHC == 8.0.2,
-                        GHC == 8.2.2,
-                        GHC == 8.4.4,
+tested-with:            GHC == 8.4.4,
                         GHC == 8.6.5,
-                        GHC == 8.8.3,
-                        GHC == 9.0.1
+                        GHC == 8.8.4,
+                        GHC == 8.10.7,
+                        GHC == 9.0.2,
+                        GHC == 9.6.1
 
 extra-source-files:     ChangeLog.md
                       , ReadMe.md
@@ -35,13 +35,13 @@
   default-language:     Haskell2010
   exposed-modules:      Data.GADT.Compare.TH
                         Data.GADT.Show.TH
-  other-modules:        Data.Dependent.Sum.TH.Internal
+  other-modules:        Data.GADT.TH.Internal
                         Data.GADT.Compare.Monad
   build-depends:        base >= 3 && <5,
                         some >= 1.0.1 && < 1.1,
                         containers >= 0.5.9.2,
                         mtl,
-                        template-haskell,
+                        template-haskell >= 2.11 && < 2.21,
                         th-abstraction >= 0.4
 
 test-suite test
diff --git a/src/Data/Dependent/Sum/TH/Internal.hs b/src/Data/Dependent/Sum/TH/Internal.hs
deleted file mode 100644
--- a/src/Data/Dependent/Sum/TH/Internal.hs
+++ /dev/null
@@ -1,128 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-
--- | Shared functions for dependent-sum-template
-module Data.Dependent.Sum.TH.Internal where
-
-import Control.Monad
-import Control.Monad.Writer
-import Data.List (foldl', drop)
-import Data.Maybe
-import Data.Map (Map)
-import qualified Data.Map as Map
-import qualified Data.Map.Merge.Lazy as Map
-import Data.Set (Set)
-import qualified Data.Set as Set
-import Language.Haskell.TH
-import Language.Haskell.TH.Datatype
-import Language.Haskell.TH.Datatype.TyVarBndr
-
-classHeadToParams :: Type -> (Name, [Type])
-classHeadToParams t = (h, reverse reversedParams)
-  where
-    (h, reversedParams) = go t
-    go :: Type -> (Name, [Type])
-    go t = case t of
-      AppT f x ->
-        let (h, reversedParams) = classHeadToParams f
-        in (h, x : reversedParams)
-      _ -> (headOfType t, [])
-
--- Do not export this type family, it must remain empty. It's used as a way to trick GHC into not unifying certain type variables.
-type family Skolem :: k -> k
-
-skolemize :: Set Name -> Type -> Type
-skolemize rigids t = case t of
-  ForallT bndrs cxt t' -> ForallT bndrs cxt (skolemize (Set.difference rigids (Set.fromList (map tvName bndrs))) t')
-  AppT t1 t2 -> AppT (skolemize rigids t1) (skolemize rigids t2)
-  SigT t k -> SigT (skolemize rigids t) k
-  VarT v -> if Set.member v rigids
-    then AppT (ConT ''Skolem) (VarT v)
-    else t
-  InfixT t1 n t2 -> InfixT (skolemize rigids t1) n (skolemize rigids t2)
-  UInfixT t1 n t2 -> UInfixT (skolemize rigids t1) n (skolemize rigids t2)
-  ParensT t -> ParensT (skolemize rigids t)
-  _ -> t
-
-reifyInstancesWithRigids :: Set Name -> Name -> [Type] -> Q [InstanceDec]
-reifyInstancesWithRigids rigids cls tys = reifyInstances cls (map (skolemize rigids) tys)
-
--- | Determine the type variables which occur freely in a type.
-freeTypeVariables :: Type -> Set Name
-freeTypeVariables t = case t of
-  ForallT bndrs _ t' -> Set.difference (freeTypeVariables t') (Set.fromList (map tvName bndrs))
-  AppT t1 t2 -> Set.union (freeTypeVariables t1) (freeTypeVariables t2)
-  SigT t _ -> freeTypeVariables t
-  VarT n -> Set.singleton n
-  _ -> Set.empty
-
-subst :: Map Name Type -> Type -> Type
-subst s = f
-  where
-    f = \case
-      ForallT bndrs cxt t ->
-        let s' = Map.difference s (Map.fromList [(k,()) | k <- map tvName bndrs])
-        in ForallT bndrs cxt (subst s' t)
-      AppT t t' -> AppT (f t) (f t')
-      SigT t k -> SigT (f t) k
-      VarT n -> case Map.lookup n s of
-        Just t -> t
-        Nothing -> VarT n
-      InfixT t x t' -> InfixT (f t) x (f t')
-      UInfixT t x t' -> UInfixT (f t) x (f t')
-      x -> x
-
--- Invoke the deriver for the given class instance.  We assume that the type
--- we're deriving for is always the first typeclass parameter, if there are
--- multiple.
-deriveForDec
-  :: Name
-  -> (DatatypeInfo -> WriterT [Type] Q Dec)
-  -> Dec
-  -> Q [Dec]
-deriveForDec className f (InstanceD overlaps cxt instanceHead decs) = do
-  let (givenClassName, firstParam : _) = classHeadToParams instanceHead
-  when (givenClassName /= className) $
-    fail $ "while deriving " ++ show className ++ ": wrong class name in prototype declaration: " ++ show givenClassName
-  let dataTypeName = headOfType firstParam
-  dataTypeInfo <- reifyDatatype dataTypeName
-  let instTypes = datatypeInstTypes dataTypeInfo
-      paramVars = Set.unions [freeTypeVariables t | t <- instTypes]
-      instTypes' = case reverse instTypes of
-        [] -> fail "deriveGEq: Not enough type parameters"
-        (_:xs) -> reverse xs
-      generatedInstanceHead = AppT (ConT className) (foldl AppT (ConT $ datatypeName dataTypeInfo) instTypes')
-  unifiedTypes <- unifyTypes [generatedInstanceHead, instanceHead]
-  let
-    newInstanceHead = applySubstitution unifiedTypes instanceHead
-    newContext = applySubstitution unifiedTypes cxt
-  -- We are not using the generated context that we collect from f, instead
-  -- relying on a correct instance head from the user
-  (dec, _) <- runWriterT $ f dataTypeInfo
-  return [InstanceD overlaps newContext newInstanceHead [dec]]
-deriveForDec className f dataDec = do
-  dataTypeInfo <- normalizeDec dataDec
-  let instTypes = datatypeInstTypes dataTypeInfo
-      paramVars = Set.unions [freeTypeVariables t | t <- instTypes]
-      instTypes' = case reverse instTypes of
-        [] -> fail "deriveGEq: Not enough type parameters"
-        (_:xs) -> reverse xs
-      instanceHead = AppT (ConT className) (foldl AppT (ConT $ datatypeName dataTypeInfo) instTypes')
-  (dec, cxt') <- runWriterT (f dataTypeInfo)
-  return [InstanceD Nothing (datatypeContext dataTypeInfo ++ cxt') instanceHead [dec]]
-
-headOfType :: Type -> Name
-headOfType = \case
-  ForallT _ _ ty -> headOfType ty
-  VarT name -> name
-  ConT name -> name
-  TupleT n -> tupleTypeName n
-  ArrowT -> ''(->)
-  ListT -> ''[]
-  AppT t _ -> headOfType t
diff --git a/src/Data/GADT/Compare/TH.hs b/src/Data/GADT/Compare/TH.hs
--- a/src/Data/GADT/Compare/TH.hs
+++ b/src/Data/GADT/Compare/TH.hs
@@ -14,7 +14,7 @@
 
 import Control.Monad
 import Control.Monad.Writer
-import Data.Dependent.Sum.TH.Internal
+import Data.GADT.TH.Internal
 import Data.Functor.Identity
 import Data.GADT.Compare
 import Data.GADT.Compare.Monad
@@ -85,10 +85,12 @@
       _ -> lift $ noBindS [| guard ($(varE l) == $(varE r)) |]
   ret <- lift $ noBindS [| return Refl |]
 
-  return $ Clause
-    [ ConP conName (map VarP lArgNames)
-    , ConP conName (map VarP rArgNames) ]
-    ( NormalB (doUnqualifiedE (stmts ++ [ret])))
+  pats <- lift $ sequence
+    [ conP conName (map varP lArgNames)
+    , conP conName (map varP rArgNames)
+    ]
+  pure $ Clause pats
+    (NormalB (doUnqualifiedE (stmts ++ [ret])))
     []
 
 class DeriveGCompare t where
@@ -150,10 +152,13 @@
 
   ret <- lift $ noBindS [| return GEQ |]
 
-  let main = Clause
-        [ ConP conName (map VarP lArgNames)
-        , ConP conName (map VarP rArgNames) ]
-        ( NormalB (AppE (VarE 'runGComparing) (doUnqualifiedE (stmts ++ [ret]))))
+
+  pats <- lift $ sequence
+        [ conP conName (map varP lArgNames)
+        , conP conName (map varP rArgNames)
+        ]
+  let main = Clause pats
+        (NormalB (AppE (VarE 'runGComparing) (doUnqualifiedE (stmts ++ [ret]))))
         []
       lt = Clause [RecP conName [], WildP] (NormalB (ConE 'GLT)) []
       gt = Clause [WildP, RecP conName []] (NormalB (ConE 'GGT)) []
diff --git a/src/Data/GADT/Show/TH.hs b/src/Data/GADT/Show/TH.hs
--- a/src/Data/GADT/Show/TH.hs
+++ b/src/Data/GADT/Show/TH.hs
@@ -6,7 +6,7 @@
 import Control.Applicative
 import Control.Monad
 import Control.Monad.Writer
-import Data.Dependent.Sum.TH.Internal
+import Data.GADT.TH.Internal
 import Data.Functor.Identity
 import Data.GADT.Show
 import Data.Traversable (for)
@@ -66,24 +66,16 @@
 
   argShowExprs <- forM (zip argNames argTypes) $ \(n,t) -> do
     let useShow = do
-          tell [AppT (ConT ''Show) t]
+          u <- lift $ reifyInstancesWithRigids paramVars ''Show [t]
+          case u of
+            (_:_) -> return ()
+            _ -> tell [AppT (ConT ''Show) t]
           return [| showsPrec 11 $(varE n) |]
     case t of
       AppT tyFun tyArg -> do
-        let useGShow = do
-              tell [AppT (ConT ''GShow) tyFun]
-              return [| gshowsPrec 11 $(varE n) |]
         if isApplicationOf (ConT typeName) tyFun
           then return [| gshowsPrec 11 $(varE n) |]
-          else do
-            v <- lift $ reifyInstancesWithRigids paramVars ''GShow [tyFun]
-            case v of
-              (_:_) -> useGShow
-              _ -> do
-                u <- lift $ reifyInstancesWithRigids paramVars ''Show [t]
-                case u of
-                  (_:_) -> useShow
-                  [] -> useGShow
+          else useShow
       _ -> useShow
 
   let precPat = if null argNames
diff --git a/src/Data/GADT/TH/Internal.hs b/src/Data/GADT/TH/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/GADT/TH/Internal.hs
@@ -0,0 +1,143 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE DataKinds #-}
+
+-- | Shared functions for dependent-sum-template
+module Data.GADT.TH.Internal where
+
+import Control.Monad
+import Control.Monad.Writer
+import qualified Data.Kind
+import Data.List (foldl', drop)
+import Data.Maybe
+import Data.Map (Map)
+import qualified Data.Map as Map
+import qualified Data.Map.Merge.Lazy as Map
+import Data.Set (Set)
+import qualified Data.Set as Set
+import Language.Haskell.TH
+import Language.Haskell.TH.Datatype
+import Language.Haskell.TH.Datatype.TyVarBndr
+
+classHeadToParams :: Type -> (Name, [Type])
+classHeadToParams t = (h, reverse reversedParams)
+  where
+    (h, reversedParams) = go t
+    go :: Type -> (Name, [Type])
+    go t = case t of
+      AppT f x ->
+        let (h, reversedParams) = classHeadToParams f
+        in (h, x : reversedParams)
+      _ -> (headOfType t, [])
+
+-- Do not export this type family, it must remain empty. It's used as a way to trick GHC into not unifying certain type variables.
+type family Skolem :: k -> k
+
+skolemize :: Set Name -> Type -> Type
+skolemize rigids t = case t of
+  ForallT bndrs cxt t' -> ForallT bndrs cxt (skolemize (Set.difference rigids (Set.fromList (map tvName bndrs))) t')
+  AppT t1 t2 -> AppT (skolemize rigids t1) (skolemize rigids t2)
+  SigT t k -> SigT (skolemize rigids t) k
+  VarT v -> if Set.member v rigids
+    then AppT (ConT ''Skolem) (VarT v)
+    else t
+  InfixT t1 n t2 -> InfixT (skolemize rigids t1) n (skolemize rigids t2)
+  UInfixT t1 n t2 -> UInfixT (skolemize rigids t1) n (skolemize rigids t2)
+  ParensT t -> ParensT (skolemize rigids t)
+  _ -> t
+
+reifyInstancesBroken :: Q Bool
+reifyInstancesBroken = do
+  a <- newName "a"
+  ins <- reifyInstancesWithRigids' (Set.singleton a) ''Show [VarT a]
+  pure $ not $ null ins
+
+reifyInstancesWithRigids' :: Set Name -> Name -> [Type] -> Q [InstanceDec]
+reifyInstancesWithRigids' rigids cls tys = reifyInstances cls (map (skolemize rigids) tys)
+
+reifyInstancesWithRigids :: Set Name -> Name -> [Type] -> Q [InstanceDec]
+reifyInstancesWithRigids rigids cls tys = do
+  isBroken <- reifyInstancesBroken
+  if isBroken
+    then fail "Unsupported GHC version: 'reifyInstances' in this version of GHC returns instances when we expect an empty list. See https://gitlab.haskell.org/ghc/ghc/-/issues/23743"
+    else reifyInstancesWithRigids' rigids cls tys
+
+-- | Determine the type variables which occur freely in a type.
+freeTypeVariables :: Type -> Set Name
+freeTypeVariables t = case t of
+  ForallT bndrs _ t' -> Set.difference (freeTypeVariables t') (Set.fromList (map tvName bndrs))
+  AppT t1 t2 -> Set.union (freeTypeVariables t1) (freeTypeVariables t2)
+  SigT t _ -> freeTypeVariables t
+  VarT n -> Set.singleton n
+  _ -> Set.empty
+
+subst :: Map Name Type -> Type -> Type
+subst s = f
+  where
+    f = \case
+      ForallT bndrs cxt t ->
+        let s' = Map.difference s (Map.fromList [(k,()) | k <- map tvName bndrs])
+        in ForallT bndrs cxt (subst s' t)
+      AppT t t' -> AppT (f t) (f t')
+      SigT t k -> SigT (f t) k
+      VarT n -> case Map.lookup n s of
+        Just t -> t
+        Nothing -> VarT n
+      InfixT t x t' -> InfixT (f t) x (f t')
+      UInfixT t x t' -> UInfixT (f t) x (f t')
+      x -> x
+
+-- Invoke the deriver for the given class instance.  We assume that the type
+-- we're deriving for is always the first typeclass parameter, if there are
+-- multiple.
+deriveForDec
+  :: Name
+  -> (DatatypeInfo -> WriterT [Type] Q Dec)
+  -> Dec
+  -> Q [Dec]
+deriveForDec className f (InstanceD overlaps cxt instanceHead decs) = do
+  let (givenClassName, firstParam : _) = classHeadToParams instanceHead
+  when (givenClassName /= className) $
+    fail $ "while deriving " ++ show className ++ ": wrong class name in prototype declaration: " ++ show givenClassName
+  let dataTypeName = headOfType firstParam
+  dataTypeInfo <- reifyDatatype dataTypeName
+  let instTypes = datatypeInstTypes dataTypeInfo
+      paramVars = Set.unions [freeTypeVariables t | t <- instTypes]
+      instTypes' = case reverse instTypes of
+        [] -> fail "deriveGEq: Not enough type parameters"
+        (_:xs) -> reverse xs
+      generatedInstanceHead = AppT (ConT className) (foldl AppT (ConT $ datatypeName dataTypeInfo) instTypes')
+  unifiedTypes <- unifyTypes [generatedInstanceHead, instanceHead]
+  let
+    newInstanceHead = applySubstitution unifiedTypes instanceHead
+    newContext = applySubstitution unifiedTypes cxt
+  -- We are not using the generated context that we collect from f, instead
+  -- relying on a correct instance head from the user
+  (dec, _) <- runWriterT $ f dataTypeInfo
+  return [InstanceD overlaps newContext newInstanceHead [dec]]
+deriveForDec className f dataDec = do
+  dataTypeInfo <- normalizeDec dataDec
+  let instTypes = datatypeInstTypes dataTypeInfo
+      paramVars = Set.unions [freeTypeVariables t | t <- instTypes]
+      instTypes' = case reverse instTypes of
+        [] -> fail "deriveGEq: Not enough type parameters"
+        (_:xs) -> reverse xs
+      instanceHead = AppT (ConT className) (foldl AppT (ConT $ datatypeName dataTypeInfo) instTypes')
+  (dec, cxt') <- runWriterT (f dataTypeInfo)
+  return [InstanceD Nothing (datatypeContext dataTypeInfo ++ cxt') instanceHead [dec]]
+
+headOfType :: Type -> Name
+headOfType = \case
+  ForallT _ _ ty -> headOfType ty
+  VarT name -> name
+  ConT name -> name
+  TupleT n -> tupleTypeName n
+  ArrowT -> ''(->)
+  ListT -> ''[]
+  AppT t _ -> headOfType t
diff --git a/test/test.hs b/test/test.hs
--- a/test/test.hs
+++ b/test/test.hs
@@ -180,7 +180,7 @@
         [d|
             instance GEq a => GEq (SpleebHard a)
             instance GCompare a => GCompare (SpleebHard a)
-            instance GShow a => GShow (SpleebHard a)
+            instance (Show (a Double), Show (a Int), GShow Qux, GShow Foo) => GShow (SpleebHard a)
           |]
 
     concat <$> sequence
@@ -189,7 +189,7 @@
         , deriveGShow    gshowInst
         ]
 
-instance GShow a => Show (SpleebHard a b) where showsPrec = gshowsPrec
+instance (Show (a Double), Show (a Int), GShow Qux, GShow Foo) => Show (SpleebHard a b) where showsPrec = gshowsPrec
 
 data SpleebHard2 a b where
     PH2 :: a Double -> Qux b -> SpleebHard2 a b
