diff --git a/.hlint.yaml b/.hlint.yaml
--- a/.hlint.yaml
+++ b/.hlint.yaml
@@ -1,4 +1,4 @@
-- arguments: [--cpp-define=HLINT, --cpp-ansi]
+- arguments: [-XCPP, --cpp-define=HLINT, --cpp-ansi]
 
 - ignore: {name: Reduce duplication}
 - ignore: {name: Redundant lambda}
diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,9 @@
+## 0.1.7 [2023.01.22]
+* Avoid a particularly dodgy use of `unsafeCoerce#` in the implementation of
+  `isNil` when building with GHC 9.4 or later. This is necessary to make the
+  `isNil` function behave properly on GHC 9.6, as changes to GHC's optimizer in
+  9.6 make that use of `unsafeCoerce#` produce unexpected results at runtime.
+
 ## 0.1.6 [2021.04.30]
 * Make the test suite compile on recent GHCs.
 
diff --git a/src/Data/Struct/Internal.hs b/src/Data/Struct/Internal.hs
--- a/src/Data/Struct/Internal.hs
+++ b/src/Data/Struct/Internal.hs
@@ -121,7 +121,31 @@
 -- >>> isNil o
 -- False
 isNil :: Struct t => t s -> Bool
-isNil t = isTrue# (unsafeCoerce# reallyUnsafePtrEquality# (destruct t) Null)
+isNil t = isTrue# (
+#if MIN_VERSION_base(4,17,0)
+  -- In base-4.17.0.0 or later, reallyUnsafePtrEquality# is levity polymorphic
+  -- and heterogeneous, so we can directly invoke it on @destruct t@ (of type
+  -- @SmallMutableArray# s Any :: UnliftedType@)) and @Null@ (of type
+  -- @Null :: Type@).
+  reallyUnsafePtrEquality#
+#else
+  -- In earlier versions of base, reallyUnsafePtrEquality#'s type is more
+  -- restrictive: both arguments must have the same type, and the type of the
+  -- arguments must be lifted (i.e., of kind @Type@). To make this work, we use
+  -- unsafeCoerce# to coerce both arguments to type @Any :: Type@, which allows
+  -- the application of reallyUnsafePtrEquality# to typecheck.
+  --
+  -- Note that we are coercing from SmallMutableArray#, an unlifted type, to
+  -- Any, a lifted type. This is on shaky ground, as GHC only guarantees that
+  -- coercing to Any works for lifted types. GHC seemed to tolerate coercing
+  -- from SmallMutableArray# to Any for many releases, but this stopped working
+  -- in GHC 9.6: see https://gitlab.haskell.org/ghc/ghc/-/issues/22813. Luckily,
+  -- we can avoid the issue by using a levity polymorphic version of
+  -- reallyUnsafePtrEquality# directly, without any intermediate coercions to
+  -- Any.
+  unsafeCoerce# reallyUnsafePtrEquality#
+#endif
+    (destruct t) Null)
 {-# INLINE isNil #-}
 
 #ifndef HLINT
diff --git a/structs.cabal b/structs.cabal
--- a/structs.cabal
+++ b/structs.cabal
@@ -1,6 +1,6 @@
 name:          structs
 category:      Data
-version:       0.1.6
+version:       0.1.7
 license:       BSD3
 cabal-version: 1.22
 license-file:  LICENSE
@@ -16,8 +16,9 @@
              , GHC == 8.4.4
              , GHC == 8.6.5
              , GHC == 8.8.4
-             , GHC == 8.10.4
-             , GHC == 9.0.1
+             , GHC == 8.10.7
+             , GHC == 9.0.2
+             , GHC == 9.2.2
 synopsis:      Strict GC'd imperative object-oriented programming with cheap pointers.
 description:
   This project is an experiment with a small GC'd strict mutable imperative universe with cheap pointers inside of the GHC runtime system.
@@ -35,7 +36,7 @@
   build-depends:
     base >= 4.9 && < 5,
     deepseq,
-    template-haskell >= 2.11 && < 2.19,
+    template-haskell >= 2.11 && < 2.20,
     th-abstraction >= 0.4 && < 0.5,
     ghc-prim,
     primitive
