diff --git a/Language/Haskell/TH/ExpandSyns.hs b/Language/Haskell/TH/ExpandSyns.hs
--- a/Language/Haskell/TH/ExpandSyns.hs
+++ b/Language/Haskell/TH/ExpandSyns.hs
@@ -28,42 +28,55 @@
 packagename :: String
 packagename = "th-expand-syns"
 
-
--- Compatibility layer for TH >=2.4 vs. 2.3
-tyVarBndrGetName :: TyVarBndr -> Name
-#if !MIN_VERSION_template_haskell(2,10,0)
-mapPred :: (Type -> Type) -> Pred -> Pred
+#if !MIN_VERSION_template_haskell(2,4,0)
+type TyVarBndr = Name
+type Pred = Type
 #endif
-bindPred :: (Type -> Q Type) -> Pred -> Q Pred
-tyVarBndrSetName :: Name -> TyVarBndr -> TyVarBndr
 
-#if MIN_VERSION_template_haskell(2,4,0)
+#if MIN_VERSION_template_haskell(2,17,0)
+tyVarBndrGetName :: TyVarBndr a -> Name
+tyVarBndrGetName (PlainTV n _) = n
+tyVarBndrGetName (KindedTV n _ _) = n
+#elif MIN_VERSION_template_haskell(2,4,0)
+tyVarBndrGetName :: TyVarBndr -> Name
 tyVarBndrGetName (PlainTV n) = n
 tyVarBndrGetName (KindedTV n _) = n
-
-#if MIN_VERSION_template_haskell(2,10,0)
-bindPred = id
 #else
-mapPred f (ClassP n ts) = ClassP n (f <$> ts)
-mapPred f (EqualP t1 t2) = EqualP (f t1) (f t2)
-
-bindPred f (ClassP n ts) = ClassP n <$> mapM f ts
-bindPred f (EqualP t1 t2) = EqualP <$> f t1 <*> f t2
+tyVarBndrGetName = id
 #endif
 
+#if MIN_VERSION_template_haskell(2,17,0)
+tyVarBndrSetName :: Name -> TyVarBndr a -> TyVarBndr a
+tyVarBndrSetName n (PlainTV _ f) = PlainTV n f
+tyVarBndrSetName n (KindedTV _ f k) = KindedTV n f k
+#elif MIN_VERSION_template_haskell(2,4,0)
+tyVarBndrSetName :: Name -> TyVarBndr -> TyVarBndr
 tyVarBndrSetName n (PlainTV _) = PlainTV n
 tyVarBndrSetName n (KindedTV _ k) = KindedTV n k
 #else
-
-type TyVarBndr = Name
-type Pred = Type
-tyVarBndrGetName = id
-mapPred = id
-bindPred = id
 tyVarBndrSetName n _ = n
+#endif
 
+#if MIN_VERSION_template_haskell(2,10,0)
+-- mapPred is not needed for template-haskell >= 2.10
+#elif MIN_VERSION_template_haskell(2,4,0)
+mapPred :: (Type -> Type) -> Pred -> Pred
+mapPred f (ClassP n ts) = ClassP n (f <$> ts)
+mapPred f (EqualP t1 t2) = EqualP (f t1) (f t2)
+#else
+mapPred = id
 #endif
 
+#if MIN_VERSION_template_haskell(2,10,0)
+bindPred :: (Type -> Q Type) -> Pred -> Q Pred
+bindPred = id
+#elif MIN_VERSION_template_haskell(2,4,0)
+bindPred :: (Type -> Q Type) -> Pred -> Q Pred
+bindPred f (ClassP n ts) = ClassP n <$> mapM f ts
+bindPred f (EqualP t1 t2) = EqualP <$> f t1 <*> f t2
+#else
+bindPred = id
+#endif
 
 #if __GLASGOW_HASKELL__ < 709
 (<$>) :: (Functor f) => (a -> b) -> f a -> f b
@@ -390,6 +403,10 @@
       go acc x@ForallVisT{} = forallAppError acc x
 #endif
 
+#if MIN_VERSION_template_haskell(2,17,0)
+      go acc x@MulArrowT = passThrough acc x
+#endif
+
 -- | An argument to a type, either a normal type ('TANormal') or a visible
 -- kind application ('TyArg').
 data TypeArg
@@ -462,6 +479,10 @@
           ForallVisT vars' (doSubsts vts' body)
 #endif
 
+#if MIN_VERSION_template_haskell(2,17,0)
+      go MulArrowT = MulArrowT
+#endif
+
 -- testCapture :: Type
 -- testCapture =
 --     let
@@ -542,7 +563,11 @@
 
 
 class HasForallConstruct a where
+#if MIN_VERSION_template_haskell(2,17,0)
+    mkForall :: [TyVarBndrSpec] -> Cxt -> a -> a
+#else
     mkForall :: [TyVarBndr] -> Cxt -> a -> a
+#endif
 
 instance HasForallConstruct Type where
     mkForall = ForallT
@@ -555,9 +580,15 @@
 -- Apply a substitution to something underneath a @forall@. The continuation
 -- argument provides new substitutions and fresh type variable binders to avoid
 -- the outer substitution from capturing the thing underneath the @forall@.
+#if MIN_VERSION_template_haskell(2,17,0)
+commonForallCase :: (Name, Type) -> [TyVarBndr flag]
+                 -> ([(Name, Type)] -> [TyVarBndr flag] -> a)
+                 -> a
+#else
 commonForallCase :: (Name, Type) -> [TyVarBndr]
                  -> ([(Name, Type)] -> [TyVarBndr] -> a)
                  -> a
+#endif
 commonForallCase vt@(v,t) bndrs k
             -- If a variable with the same name as the one to be replaced is bound by the forall,
             -- the variable to be replaced is shadowed in the body, so we leave the whole thing alone (no recursion)
diff --git a/changelog.markdown b/changelog.markdown
--- a/changelog.markdown
+++ b/changelog.markdown
@@ -1,3 +1,7 @@
+## 0.4.7.0
+
+* Support GHC 9.0 / template-haskell-2.17 (Thanks to @mgsloan)
+
 ## 0.4.5.0
 
 * Support GHC 8.8 / template-haskell-2.15 (Thanks to Ryan Scott)
diff --git a/testing/Types.hs b/testing/Types.hs
--- a/testing/Types.hs
+++ b/testing/Types.hs
@@ -19,7 +19,7 @@
 type Id a = a
 
 -- type E x = forall y. Either x y -> Int
-$(sequence [tySynD (mkName "E") [PlainTV (mkName "x")]
+$(sequence [tySynD (mkName "E") [plainTV (mkName "x")]
                 (forallT'' ["y"] (conT ''Either `appT` varT' "x" `appT` varT' "y" --> conT ''Int))
            ])
 
diff --git a/testing/Util.hs b/testing/Util.hs
--- a/testing/Util.hs
+++ b/testing/Util.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE CPP             #-}
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE CPP                       #-}
+{-# LANGUAGE TemplateHaskell           #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
 module Util where
 import           Language.Haskell.TH
 import           Language.Haskell.TH.ExpandSyns
@@ -16,10 +17,10 @@
       if (pprint expected'==pprint actual) then [| putStrLn "Ok" |] else [| error "expected /= actual" |]
 
 
-forallT' xs = forallT ((PlainTV . mkName) `fmap` xs)
+forallT' xs = forallT ((\x -> PlainTV (mkName x) SpecifiedSpec) `fmap` xs)
 forallT'' xs = forallT' xs (cxt [])
 varT' = varT . mkName
-conT' = conT . mkName
+conT' x = conT . mkName
 
 x --> y = (arrowT `appT` x) `appT` y
 infixr 5 -->
diff --git a/th-expand-syns.cabal b/th-expand-syns.cabal
--- a/th-expand-syns.cabal
+++ b/th-expand-syns.cabal
@@ -1,5 +1,5 @@
 name:                th-expand-syns
-version:             0.4.6.0
+version:             0.4.7.0
 synopsis:            Expands type synonyms in Template Haskell ASTs
 description:         Expands type synonyms in Template Haskell ASTs.
 category:            Template Haskell
@@ -7,7 +7,7 @@
 license-file:        LICENSE
 author:              Daniel Schüssler
 maintainer:          haskell.5wlh@gishpuppy.com
-cabal-version:       >= 1.8
+cabal-version:       >= 1.10
 build-type:          Simple
 extra-source-files:  changelog.markdown
 homepage:            https://github.com/DanielSchuessler/th-expand-syns
@@ -23,10 +23,11 @@
  location: git://github.com/DanielSchuessler/th-expand-syns.git
 
 Library
-    build-depends:       base >= 4 && < 5, template-haskell < 2.17, syb, containers
+    build-depends:       base >= 4 && < 5, template-haskell < 2.18, syb, containers
     ghc-options:
     exposed-modules:     Language.Haskell.TH.ExpandSyns
     other-modules:       Language.Haskell.TH.ExpandSyns.SemigroupCompat
+    default-language:    Haskell2010
 
 Test-Suite test-th-expand-syns
     type:               exitcode-stdio-1.0
@@ -34,3 +35,4 @@
     main-is:            Main.hs
     other-modules:      Util, Types
     build-depends:      base, th-expand-syns, template-haskell
+    default-language:   Haskell2010
