diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# network-uri-2.6.4.0 (2021-02-07)
+* Add compatibility with GHC 9.0.1.
+
 # network-uri-2.6.3.0 (2020-02-18)
 * Add official support for SafeHaskell
   NOTE: This is the first version whose SafeHaskell properties have become an
diff --git a/Network/URI/Lens.hs b/Network/URI/Lens.hs
--- a/Network/URI/Lens.hs
+++ b/Network/URI/Lens.hs
@@ -17,7 +17,9 @@
   , uriFragmentLens
   ) where
 
+#if __GLASGOW_HASKELL__ < 710
 import           Control.Applicative
+#endif
 import           Network.URI
 
 type Lens' s a = Lens s s a a
diff --git a/Network/URI/Static.hs b/Network/URI/Static.hs
--- a/Network/URI/Static.hs
+++ b/Network/URI/Static.hs
@@ -4,7 +4,7 @@
 {-# LANGUAGE RecordWildCards, TemplateHaskellQuotes, ViewPatterns #-}
 #endif
 #if MIN_VERSION_template_haskell(2,12,0)
-{-# LANGUAGE Safe #-}
+-- {-# LANGUAGE Safe #-}
 #elif __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE Trustworthy #-}
 #endif
@@ -29,8 +29,7 @@
 import Network.URI (URI(..), parseURI, parseRelativeReference)
 
 #if __GLASGOW_HASKELL__ >= 708
-import Language.Haskell.TH.Lib (TExpQ)
-import Language.Haskell.TH.Syntax (unTypeQ)
+import Language.Haskell.TH.Syntax.Compat (SpliceQ, unTypeCode, toCode)
 #endif
 
 -- $setup
@@ -54,10 +53,10 @@
 -- <interactive>...
 -- ... Invalid URI: http://www.google.com/##
 -- ...
-staticURI :: String    -- ^ String representation of a URI
-          -> TExpQ URI -- ^ URI
+staticURI :: String      -- ^ String representation of a URI
+          -> SpliceQ URI -- ^ URI
 staticURI (parseURI -> Just u) = [|| u ||]
-staticURI s = fail $ "Invalid URI: " ++ s
+staticURI s = error $ "Invalid URI: " ++ s
 #endif
 
 -- | 'staticURI'' parses a specified string at compile time.
@@ -66,7 +65,7 @@
 staticURI' :: String    -- ^ String representation of a URI
            -> ExpQ      -- ^ URI
 #if __GLASGOW_HASKELL__ >= 708
-staticURI' = unTypeQ . staticURI
+staticURI' = unTypeCode . toCode . staticURI
 #else
 staticURI' (parseURI -> Just u) = [| u |]
 staticURI' s = fail $ "Invalid URI: " ++ s
@@ -107,10 +106,10 @@
 -- <interactive>...
 -- ... Invalid relative reference: http://www.google.com/
 -- ...
-staticRelativeReference :: String -- ^ String representation of a reference
-                        -> TExpQ URI -- ^ Refererence
+staticRelativeReference :: String      -- ^ String representation of a reference
+                        -> SpliceQ URI -- ^ Refererence
 staticRelativeReference (parseRelativeReference -> Just ref) = [|| ref ||]
-staticRelativeReference ref = fail $ "Invalid relative reference: " ++ ref
+staticRelativeReference ref = error $ "Invalid relative reference: " ++ ref
 #endif
 
 -- | 'staticRelativeReference'' parses a specified string at compile time and
@@ -121,7 +120,7 @@
 staticRelativeReference' :: String -- ^ String representation of a reference
                          -> ExpQ   -- ^ Refererence
 #if __GLASGOW_HASKELL__ >= 708
-staticRelativeReference' = unTypeQ . staticRelativeReference
+staticRelativeReference' = unTypeCode . toCode . staticRelativeReference
 #else
 staticRelativeReference' (parseRelativeReference -> Just ref) = [| ref |]
 staticRelativeReference' ref = fail $ "Invalid relative reference: " ++ ref
diff --git a/network-uri.cabal b/network-uri.cabal
--- a/network-uri.cabal
+++ b/network-uri.cabal
@@ -1,5 +1,5 @@
 name:                network-uri
-version:             2.6.3.0
+version:             2.6.4.0
 synopsis:            URI manipulation
 description:
   This package provides facilities for parsing and unparsing URIs, and creating
@@ -46,7 +46,8 @@
 build-type:          Simple
 cabal-version:       >=1.10
 tested-with:
-  GHC ==8.10.1
+  GHC ==9.0.1
+   || ==8.10.1
    || ==8.8.2
    || ==8.6.5
    || ==8.4.4
@@ -57,7 +58,7 @@
    || ==7.6.3
    || ==7.4.2
    || ==7.2.2
-   || ==7.0.2
+   || ==7.0.4
 
 library
   exposed-modules:
@@ -67,7 +68,8 @@
   build-depends:
     base >= 3 && < 5,
     deepseq >= 1.1 && < 1.5,
-    parsec >= 3.1.12.0 && < 3.2
+    parsec >= 3.1.12.0 && < 3.2,
+    th-compat >= 0.1 && < 1.0
   build-depends: template-haskell
   default-extensions: CPP, DeriveDataTypeable
   if impl(ghc < 7.6)
@@ -86,14 +88,15 @@
     base < 5,
     HUnit,
     network-uri,
-    test-framework,
-    test-framework-hunit,
-    test-framework-quickcheck2
+    tasty,
+    tasty-hunit,
+    tasty-quickcheck,
+    QuickCheck
 
   ghc-options: -Wall -fwarn-tabs
   default-language: Haskell98
 
-test-suite uri-bench
+benchmark uri-bench
   hs-source-dirs: tests
   main-is: uri-bench.hs
   type: exitcode-stdio-1.0
diff --git a/tests/uri001.hs b/tests/uri001.hs
--- a/tests/uri001.hs
+++ b/tests/uri001.hs
@@ -54,12 +54,15 @@
 
 import Test.HUnit
 
+import Data.Bits ((.&.), (.|.))
+import Data.Char (ord, chr)
 import Data.Maybe (fromJust)
 import Data.List (intercalate)
 import System.IO (openFile, IOMode(WriteMode), hClose)
-import qualified Test.Framework as TF
-import qualified Test.Framework.Providers.HUnit as TF
-import qualified Test.Framework.Providers.QuickCheck2 as TF
+import qualified Test.Tasty as TF
+import qualified Test.Tasty.HUnit as TF
+import qualified Test.Tasty.QuickCheck as TF
+import Test.QuickCheck ((==>), Property)
 
 -- Test supplied string for valid URI reference syntax
 --   isValidURIRef :: String -> Bool
@@ -1108,12 +1111,31 @@
     "hello%C3%B8%C2%A9%E6%97%A5%E6%9C%AC"
     (escapeURIString isUnescapedInURIComponent "helloø©日本")
 
-propEscapeUnEscapeLoop :: String -> Bool
-propEscapeUnEscapeLoop s = s == (unEscapeString $! escaped)
+validUnicodePoint :: Char -> Bool
+validUnicodePoint c =
+  case ord c of
+    c | c >= 0xFDD0 && c <= 0xFDEF -> False
+    c | c .&. 0xFFFE == 0xFFFE -> False
+    _ -> True
+
+propEscapeUnEscapeLoop :: String -> Property
+propEscapeUnEscapeLoop s =
+  all validUnicodePoint s ==>
+  s == (unEscapeString $! escaped)
         where
         escaped = escapeURIString (const False) s
         {-# NOINLINE escaped #-}
 
+-- Test some Unicode chars high in the Basic Multilingual Plane.
+propEscapeUnEscapeLoopHiChars :: Char -> Property
+propEscapeUnEscapeLoopHiChars c' =
+  let c = chr $ (ord c') .|. 0xff00 in
+  validUnicodePoint c ==>
+  [c] == (unEscapeString $! escaped c)
+        where
+        escaped c = escapeURIString (const False) [c]
+        {-# NOINLINE escaped #-}
+
 testEscapeURIString = TF.testGroup "testEscapeURIString"
   [ TF.testCase "testEscapeURIString01" testEscapeURIString01
   , TF.testCase "testEscapeURIString02" testEscapeURIString02
@@ -1122,6 +1144,7 @@
   , TF.testCase "testEscapeURIString05" testEscapeURIString05
   , TF.testCase "testEscapeURIString06" testEscapeURIString06
   , TF.testProperty "propEscapeUnEscapeLoop" propEscapeUnEscapeLoop
+  , TF.testProperty "propEscapeUnEscapeLoopHiChars" propEscapeUnEscapeLoopHiChars
   ]
 
 -- URI string normalization tests
@@ -1330,7 +1353,7 @@
   ]
 
 -- Full test suite
-allTests =
+allTests = TF.testGroup "all"
   [ testURIRefSuite
   , testComponentSuite
   , testRelativeSuite
