diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,9 @@
+## 0.1.8 [2023.02.22]
+* Avoid some dodgy uses of `unsafeCoerce#` from `Any` (a lifted type) to
+  `MutableByteArray# s` (an unlifted type) in the internals of the library.
+  While these uses of `unsafeCoerce#` have not been observed to cause any
+  improper behavior at runtime, the previous situation was rather delicate.
+
 ## 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
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
@@ -1,6 +1,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE Unsafe #-}
+{-# LANGUAGE DataKinds #-}
 {-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE MagicHash #-}
 {-# LANGUAGE RankNTypes #-}
@@ -11,6 +12,11 @@
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE DefaultSignatures #-}
+
+#if __GLASGOW_HASKELL__ < 806
+{-# LANGUAGE TypeInType #-}
+#endif
+
 {-# OPTIONS_HADDOCK not-home #-}
 -----------------------------------------------------------------------------
 -- |
@@ -31,6 +37,10 @@
 import Data.Coerce
 import GHC.Exts
 
+#if MIN_VERSION_base(4,15,0)
+import Unsafe.Coerce (unsafeCoerceUnlifted)
+#endif
+
 -- $setup
 -- >>> import Control.Monad.Primitive
 
@@ -159,26 +169,92 @@
 -- * Faking SmallMutableArrayArray#s
 --------------------------------------------------------------------------------
 
+{-
+The types of writeSmallArray#, readSmallArray#, and casSmallArray# became
+levity polymorphic in @base-4.17.0.0@, which allows us to coerce from a
+@SmallMutableArray# s Any@ to a @SmallMutableArray# s (SmallMutableArray# s
+Any)@ or a @SmallMutableArray# s MutableByteArray#@. These types are all of
+kind UnliftedType, so we can accomplish this coercion using
+unsafeCoerceUnlifted instead of its dodgier alternative, unsafeCoerce#.
+
+On older versions of base, SmallMutableArray# is of kind @Type -> Type ->
+UnliftedType@, so we must resort to sketchier uses of unsafeCoerce#. For
+instance, the implementation of readMutableByteArraySmallArray# must coerce from
+this type:
+
+  SmallMutableArray# s Any -> Int# -> State# s -> (# State# s, Any #)
+
+To this type:
+
+  SmallMutableArray# s Any -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
+
+This implies coercing (Any :: Type) to (MutableByteArray# s :: UnliftedType).
+This is on shaky ground, as the coercion changes a lifted type to an unlifted
+type! Unfortunately, we can't really do better given SmallMutableArray#'s
+restrictive kind.
+
+Note that both the pre- and post-@base-4.17.0.0@ versions of the code use the
+same number of unsafe coercions. The difference lies in whether you are
+coercing from @Any@ to @MutableByteArray# s@ (a kind-heterogeneous coercion)
+versus coercing from @SmallMutableArray# s Any@ to @SmallMutableArray# s
+(MutableByteArray# s)@ (a kind-homogeneous coercion). You'll still need /some/
+sort of unsafe coercion given the fact that the @structs@ library uniformly
+represents everything as @SmallMutableArray# s Any@, but at the very least, the
+latter types of coercions avoid casting directly from lifted to unlifted types.
+
+See https://gitlab.haskell.org/ghc/ghc/-/issues/22813 for the GHC issue that
+led to the current design of this code.
+-}
+
 writeSmallMutableArraySmallArray# :: SmallMutableArray# s Any -> Int# -> SmallMutableArray# s Any -> State# s -> State# s
+#if MIN_VERSION_base(4,17,0)
+writeSmallMutableArraySmallArray# m i a s = writeSmallArray# (unsafeCoerceUnlifted m) i a s
+#else
 writeSmallMutableArraySmallArray# m i a s = unsafeCoerce# writeSmallArray# m i a s
+#endif
 {-# INLINE writeSmallMutableArraySmallArray# #-}
 
 readSmallMutableArraySmallArray# :: SmallMutableArray# s Any -> Int# -> State# s -> (# State# s, SmallMutableArray# s Any #)
+#if MIN_VERSION_base(4,17,0)
+readSmallMutableArraySmallArray# m i s = readSmallArray# (unsafeCoerceUnlifted m) i s
+#else
 readSmallMutableArraySmallArray# m i s = unsafeCoerce# readSmallArray# m i s
+#endif
 {-# INLINE readSmallMutableArraySmallArray# #-}
 
 writeMutableByteArraySmallArray# :: SmallMutableArray# s Any -> Int# -> MutableByteArray# s -> State# s -> State# s
+#if MIN_VERSION_base(4,17,0)
+writeMutableByteArraySmallArray# m i a s = writeSmallArray# (unsafeCoerceUnlifted m) i a s
+#else
 writeMutableByteArraySmallArray# m i a s = unsafeCoerce# writeSmallArray# m i a s
+#endif
 {-# INLINE writeMutableByteArraySmallArray# #-}
 
 readMutableByteArraySmallArray# :: SmallMutableArray# s Any -> Int# -> State# s -> (# State# s, MutableByteArray# s #)
+#if MIN_VERSION_base(4,17,0)
+readMutableByteArraySmallArray# m i s = readSmallArray# (unsafeCoerceUnlifted m) i s
+#else
 readMutableByteArraySmallArray# m i s = unsafeCoerce# readSmallArray# m i s
+#endif
 {-# INLINE readMutableByteArraySmallArray# #-}
 
 casSmallMutableArraySmallArray# :: SmallMutableArray# s Any -> Int# -> SmallMutableArray# s Any -> SmallMutableArray# s Any -> State# s -> (# State# s, Int#, SmallMutableArray# s Any #)
+#if MIN_VERSION_base(4,17,0)
+casSmallMutableArraySmallArray# m i o n s = casSmallArray# (unsafeCoerceUnlifted m) i o n s
+#else
 casSmallMutableArraySmallArray# m i o n s = unsafeCoerce# casSmallArray# m i o n s
+#endif
 {-# INLINE casSmallMutableArraySmallArray# #-}
 
+#if !(MIN_VERSION_base(4,15,0))
+unsafeCoerceUnlifted :: forall (a :: TYPE UnliftedRep) (b :: TYPE UnliftedRep). a -> b
+unsafeCoerceUnlifted = unsafeCoerce#
+#endif
+
+#if !(MIN_VERSION_base(4,10,0))
+type UnliftedRep = PtrRepUnlifted
+#endif
+
 --------------------------------------------------------------------------------
 -- * Field Accessors
 --------------------------------------------------------------------------------
@@ -235,8 +311,8 @@
 -- | Store the reference to the Haskell data type in a normal field
 field :: Int {- ^ slot -} -> Field s a
 field (I# i) = Field
-  (\m s -> unsafeCoerce# readSmallArray# m i s)
-  (\m a s -> unsafeCoerce# writeSmallArray# m i a s)
+  (\m s -> readSmallArray# (unsafeCoerceUnlifted m) i s)
+  (\m a s -> writeSmallArray# (unsafeCoerceUnlifted m) i a s)
 {-# INLINE field #-}
 
 -- | Store the reference in the nth slot in the nth argument, treated as a MutableByteArray
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.7
+version:       0.1.8
 license:       BSD3
 cabal-version: 1.22
 license-file:  LICENSE
@@ -53,6 +53,7 @@
     Data.Struct.Order
 
   ghc-options: -Wall -fwarn-monomorphism-restriction -fwarn-identities -fwarn-incomplete-record-updates -fwarn-incomplete-uni-patterns -fno-warn-wrong-do-bind
+               -Wno-unticked-promoted-constructors
   hs-source-dirs: src
   default-language: Haskell2010
 
