    {-# LANGUAGE CPP #-}
    -- | A compat module to take fixed points in 'Q'.
    module TH.FixQ (fixQ) where

    #if MIN_VERSION_template_haskell(2,17,0)
    import Control.Monad.Fix (mfix)
    import Language.Haskell.TH.Syntax (Q (..))

    fixQ :: (a -> Q a) -> Q a
    fixQ :: forall a. (a -> Q a) -> Q a
    fixQ = (a -> Q a) -> Q a
    forall a. (a -> Q a) -> Q a
    forall (m :: * -> *) a. MonadFix m => (a -> m a) -> m a
    mfix

    #else

    -- We don't have a MonadFix instance for Q
    import Control.Concurrent.MVar (newEmptyMVar, readMVar, putMVar)
    import Control.Exception (BlockedIndefinitelyOnMVar (..), catch, throwIO)
    import Control.Exception.Base (FixIOException (..))
    import Language.Haskell.TH.Syntax (Q (..), runIO)
    import GHC.IO.Unsafe (unsafeDupableInterleaveIO)

    fixQ :: (a -> Q a) -> Q a
    fixQ k = do
      m <- runIO newEmptyMVar
      ans <- runIO (unsafeDupableInterleaveIO
               (readMVar m `catch` \BlockedIndefinitelyOnMVar ->
                                      throwIO FixIOException))
      result <- k ans
      runIO (putMVar m result)
      return result

    #endif