    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE ExistentialQuantification #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE ImplicitParams #-}
    -- | Unlifted "Control.Exception", with extra async exception safety
    -- and more helper functions.
    --
    -- This module works best when your cleanup functions adhere to certain
    -- expectations around exception safety and interruptible actions.
    -- For more details, see [this exception safety tutorial](https://haskell.fpcomplete.com/tutorial/exceptions).
    module UnliftIO.Exception
      ( -- * Throwing
        throwIO
      , throwString
      , StringException (..)
      , stringException
      , throwTo
      , impureThrow
      , fromEither
      , fromEitherIO
      , fromEitherM
        -- * Catching (with recovery)
      , catch
      , catchIO
      , catchAny
      , catchDeep
      , catchAnyDeep
      , catchJust

      , handle
      , handleIO
      , handleAny
      , handleDeep
      , handleAnyDeep
      , handleJust

      , try
      , tryIO
      , tryAny
      , tryDeep
      , tryAnyDeep
      , tryJust
      , pureTry
      , pureTryDeep

      , Handler(..)
      , catches
      , catchesDeep

        -- * Cleanup (no recovery)
      , onException
      , bracket
      , bracket_
      , finally
      , withException
      , bracketOnError
      , bracketOnError_

        -- * Coercion to sync and async
      , SyncExceptionWrapper (..)
      , toSyncException
      , AsyncExceptionWrapper (..)
      , toAsyncException

        -- * Check exception type
      , isSyncException
      , isAsyncException
        -- * Masking
      , mask
      , uninterruptibleMask
      , mask_
      , uninterruptibleMask_
        -- * Evaluation
      , evaluate
      , evaluateDeep
        -- * Reexports
      , Exception (..)
      , Typeable
      , SomeException (..)
      , SomeAsyncException (..)
      , IOException
      , EUnsafe.assert
    #if !MIN_VERSION_base(4,8,0)
      , displayException
    #endif
      ) where

    import Control.Concurrent (ThreadId)
    import Control.Monad (liftM)
    import Control.Monad.IO.Unlift
    import Control.Exception (Exception (..), SomeException (..), IOException, SomeAsyncException (..))
    import qualified Control.Exception as EUnsafe
    import Control.DeepSeq (NFData (..), ($!!))
    import Data.Typeable (Typeable, cast)
    import System.IO.Unsafe (unsafePerformIO)

    #if MIN_VERSION_base(4,9,0)
    import GHC.Stack (prettySrcLoc)
    import GHC.Stack.Types (HasCallStack, CallStack, getCallStack)
    #endif

    -- | Unlifted 'EUnsafe.catch', but will not catch asynchronous exceptions.
    --
    -- @since 0.1.0.0
    catch :: (MonadUnliftIO m, Exception e) => m a -> (e -> m a) -> m a
    catch :: m a -> (e -> m a) -> m a
    catch f :: m a
    f g :: e -> m a
    g = ((forall a. m a -> IO a) -> IO a) -> m a
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO a) -> m a)
    -> ((forall a. m a -> IO a) -> IO a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> m a -> IO a
    forall a. m a -> IO a
    run m a
    f IO a -> (e -> IO a) -> IO a
    forall e a. Exception e => IO a -> (e -> IO a) -> IO a
    `EUnsafe.catch` \e :: e
    e ->
      if e -> Bool
    forall e. Exception e => e -> Bool
    isSyncException e
    e
        then m a -> IO a
    forall a. m a -> IO a
    run (e -> m a
    g e
    e)
        -- intentionally rethrowing an async exception synchronously,
        -- since we want to preserve async behavior
        else e -> IO a
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO e
    e

    -- | 'catch' specialized to only catching 'IOException's.
    --
    -- @since 0.1.0.0
    catchIO :: MonadUnliftIO m => m a -> (IOException -> m a) -> m a
    catchIO :: m a -> (IOException -> m a) -> m a
    catchIO = m a -> (IOException -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch

    -- | 'catch' specialized to catch all synchronous exception.
    --
    -- @since 0.1.0.0
    catchAny :: MonadUnliftIO m => m a -> (SomeException -> m a) -> m a
    catchAny :: m a -> (SomeException -> m a) -> m a
    catchAny = m a -> (SomeException -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch

    -- | Same as 'catch', but fully force evaluation of the result value
    -- to find all impure exceptions.
    --
    -- @since 0.1.0.0
    catchDeep :: (MonadUnliftIO m, Exception e, NFData a)
              => m a -> (e -> m a) -> m a
    catchDeep :: m a -> (e -> m a) -> m a
    catchDeep m :: m a
    m = m a -> (e -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch (m a
    m m a -> (a -> m a) -> m a
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> m a
    forall (m :: * -> *) a. (MonadIO m, NFData a) => a -> m a
    evaluateDeep)

    -- | 'catchDeep' specialized to catch all synchronous exception.
    --
    -- @since 0.1.0.0
    catchAnyDeep :: (NFData a, MonadUnliftIO m) => m a -> (SomeException -> m a) -> m a
    catchAnyDeep :: m a -> (SomeException -> m a) -> m a
    catchAnyDeep = m a -> (SomeException -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e, NFData a) =>
    m a -> (e -> m a) -> m a
    catchDeep

    -- | 'catchJust' is like 'catch' but it takes an extra argument which
    -- is an exception predicate, a function which selects which type of
    -- exceptions we're interested in.
    --
    -- @since 0.1.0.0
    catchJust :: (MonadUnliftIO m, Exception e) => (e -> Maybe b) -> m a -> (b -> m a) -> m a
    catchJust :: (e -> Maybe b) -> m a -> (b -> m a) -> m a
    catchJust f :: e -> Maybe b
    f a :: m a
    a b :: b -> m a
    b = m a
    a m a -> (e -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    `catch` \e :: e
    e -> m a -> (b -> m a) -> Maybe b -> m a
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (e -> IO a
    forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
    throwIO e
    e)) b -> m a
    b (Maybe b -> m a) -> Maybe b -> m a
    forall a b. (a -> b) -> a -> b
    $ e -> Maybe b
    f e
    e

    -- | Flipped version of 'catch'.
    --
    -- @since 0.1.0.0
    handle :: (MonadUnliftIO m, Exception e) => (e -> m a) -> m a -> m a
    handle :: (e -> m a) -> m a -> m a
    handle = (m a -> (e -> m a) -> m a) -> (e -> m a) -> m a -> m a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip m a -> (e -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch

    -- | 'handle' specialized to only catching 'IOException's.
    --
    -- @since 0.1.0.0
    handleIO :: MonadUnliftIO m => (IOException -> m a) -> m a -> m a
    handleIO :: (IOException -> m a) -> m a -> m a
    handleIO = (IOException -> m a) -> m a -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    (e -> m a) -> m a -> m a
    handle

    -- | Flipped version of 'catchAny'.
    --
    -- @since 0.1.0.0
    handleAny :: MonadUnliftIO m => (SomeException -> m a) -> m a -> m a
    handleAny :: (SomeException -> m a) -> m a -> m a
    handleAny = (SomeException -> m a) -> m a -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    (e -> m a) -> m a -> m a
    handle

    -- | Flipped version of 'catchDeep'.
    --
    -- @since 0.1.0.0
    handleDeep :: (MonadUnliftIO m, Exception e, NFData a) => (e -> m a) -> m a -> m a
    handleDeep :: (e -> m a) -> m a -> m a
    handleDeep = (m a -> (e -> m a) -> m a) -> (e -> m a) -> m a -> m a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip m a -> (e -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e, NFData a) =>
    m a -> (e -> m a) -> m a
    catchDeep

    -- | Flipped version of 'catchAnyDeep'.
    --
    -- @since 0.1.0.0
    handleAnyDeep :: (MonadUnliftIO m, NFData a) => (SomeException -> m a) -> m a -> m a
    handleAnyDeep :: (SomeException -> m a) -> m a -> m a
    handleAnyDeep = (m a -> (SomeException -> m a) -> m a)
    -> (SomeException -> m a) -> m a -> m a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip m a -> (SomeException -> m a) -> m a
    forall a (m :: * -> *).
    (NFData a, MonadUnliftIO m) =>
    m a -> (SomeException -> m a) -> m a
    catchAnyDeep

    -- | Flipped 'catchJust'.
    --
    -- @since 0.1.0.0
    handleJust :: (MonadUnliftIO m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
    handleJust :: (e -> Maybe b) -> (b -> m a) -> m a -> m a
    handleJust f :: e -> Maybe b
    f = (m a -> (b -> m a) -> m a) -> (b -> m a) -> m a -> m a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip ((e -> Maybe b) -> m a -> (b -> m a) -> m a
    forall (m :: * -> *) e b a.
    (MonadUnliftIO m, Exception e) =>
    (e -> Maybe b) -> m a -> (b -> m a) -> m a
    catchJust e -> Maybe b
    f)

    -- | Unlifted 'EUnsafe.try', but will not catch asynchronous exceptions.
    --
    -- @since 0.1.0.0
    try :: (MonadUnliftIO m, Exception e) => m a -> m (Either e a)
    try :: m a -> m (Either e a)
    try f :: m a
    f = m (Either e a) -> (e -> m (Either e a)) -> m (Either e a)
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch ((a -> Either e a) -> m a -> m (Either e a)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM a -> Either e a
    forall a b. b -> Either a b
    Right m a
    f) (Either e a -> m (Either e a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either e a -> m (Either e a))
    -> (e -> Either e a) -> e -> m (Either e a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> Either e a
    forall a b. a -> Either a b
    Left)

    -- | 'try' specialized to only catching 'IOException's.
    --
    -- @since 0.1.0.0
    tryIO :: MonadUnliftIO m => m a -> m (Either IOException a)
    tryIO :: m a -> m (Either IOException a)
    tryIO = m a -> m (Either IOException a)
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> m (Either e a)
    try

    -- | 'try' specialized to catch all synchronous exceptions.
    --
    -- @since 0.1.0.0
    tryAny :: MonadUnliftIO m => m a -> m (Either SomeException a)
    tryAny :: m a -> m (Either SomeException a)
    tryAny = m a -> m (Either SomeException a)
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> m (Either e a)
    try

    -- | Same as 'try', but fully force evaluation of the result value
    -- to find all impure exceptions.
    --
    -- @since 0.1.0.0
    tryDeep :: (MonadUnliftIO m, Exception e, NFData a) => m a -> m (Either e a)
    tryDeep :: m a -> m (Either e a)
    tryDeep f :: m a
    f = m (Either e a) -> (e -> m (Either e a)) -> m (Either e a)
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch ((a -> Either e a) -> m a -> m (Either e a)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM a -> Either e a
    forall a b. b -> Either a b
    Right (m a
    f m a -> (a -> m a) -> m a
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> m a
    forall (m :: * -> *) a. (MonadIO m, NFData a) => a -> m a
    evaluateDeep)) (Either e a -> m (Either e a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either e a -> m (Either e a))
    -> (e -> Either e a) -> e -> m (Either e a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> Either e a
    forall a b. a -> Either a b
    Left)

    -- | 'tryDeep' specialized to catch all synchronous exceptions.
    --
    -- @since 0.1.0.0
    tryAnyDeep :: (MonadUnliftIO m, NFData a) => m a -> m (Either SomeException a)
    tryAnyDeep :: m a -> m (Either SomeException a)
    tryAnyDeep = m a -> m (Either SomeException a)
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e, NFData a) =>
    m a -> m (Either e a)
    tryDeep

    -- | A variant of 'try' that takes an exception predicate to select
    -- which exceptions are caught.
    --
    -- @since 0.1.0.0
    tryJust :: (MonadUnliftIO m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
    tryJust :: (e -> Maybe b) -> m a -> m (Either b a)
    tryJust f :: e -> Maybe b
    f a :: m a
    a = m (Either b a) -> (e -> m (Either b a)) -> m (Either b a)
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    catch (a -> Either b a
    forall a b. b -> Either a b
    Right (a -> Either b a) -> m a -> m (Either b a)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    `liftM` m a
    a) (\e :: e
    e -> m (Either b a)
    -> (b -> m (Either b a)) -> Maybe b -> m (Either b a)
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (e -> m (Either b a)
    forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
    throwIO e
    e) (Either b a -> m (Either b a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either b a -> m (Either b a))
    -> (b -> Either b a) -> b -> m (Either b a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . b -> Either b a
    forall a b. a -> Either a b
    Left) (e -> Maybe b
    f e
    e))

    -- | Evaluate the value to WHNF and catch any synchronous exceptions.
    --
    -- The expression may still have bottom values within it; you may
    -- instead want to use 'pureTryDeep'.
    --
    -- @since 0.2.2.0
    pureTry :: a -> Either SomeException a
    pureTry :: a -> Either SomeException a
    pureTry a :: a
    a = IO (Either SomeException a) -> Either SomeException a
    forall a. IO a -> a
    unsafePerformIO (IO (Either SomeException a) -> Either SomeException a)
    -> IO (Either SomeException a) -> Either SomeException a
    forall a b. (a -> b) -> a -> b
    $ (Either SomeException a -> IO (Either SomeException a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either SomeException a -> IO (Either SomeException a))
    -> Either SomeException a -> IO (Either SomeException a)
    forall a b. (a -> b) -> a -> b
    $! a -> Either SomeException a
    forall a b. b -> Either a b
    Right (a -> Either SomeException a) -> a -> Either SomeException a
    forall a b. (a -> b) -> a -> b
    $! a
    a) IO (Either SomeException a)
    -> (SomeException -> IO (Either SomeException a))
    -> IO (Either SomeException a)
    forall (m :: * -> *) a.
    MonadUnliftIO m =>
    m a -> (SomeException -> m a) -> m a
    `catchAny` (Either SomeException a -> IO (Either SomeException a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either SomeException a -> IO (Either SomeException a))
    -> (SomeException -> Either SomeException a)
    -> SomeException
    -> IO (Either SomeException a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SomeException -> Either SomeException a
    forall a b. a -> Either a b
    Left)

    -- | Evaluate the value to NF and catch any synchronous exceptions.
    --
    -- @since 0.2.2.0
    pureTryDeep :: NFData a => a -> Either SomeException a
    pureTryDeep :: a -> Either SomeException a
    pureTryDeep = IO (Either SomeException a) -> Either SomeException a
    forall a. IO a -> a
    unsafePerformIO (IO (Either SomeException a) -> Either SomeException a)
    -> (a -> IO (Either SomeException a))
    -> a
    -> Either SomeException a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO a -> IO (Either SomeException a)
    forall (m :: * -> *) a.
    (MonadUnliftIO m, NFData a) =>
    m a -> m (Either SomeException a)
    tryAnyDeep (IO a -> IO (Either SomeException a))
    -> (a -> IO a) -> a -> IO (Either SomeException a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return

    -- | Generalized version of 'EUnsafe.Handler'.
    --
    -- @since 0.1.0.0
    data Handler m a = forall e . Exception e => Handler (e -> m a)

    -- | Internal.
    catchesHandler :: MonadIO m => [Handler m a] -> SomeException -> m a
    catchesHandler :: [Handler m a] -> SomeException -> m a
    catchesHandler handlers :: [Handler m a]
    handlers e :: SomeException
    e = (Handler m a -> m a -> m a) -> m a -> [Handler m a] -> m a
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr Handler m a -> m a -> m a
    forall (m :: * -> *) a. Handler m a -> m a -> m a
    tryHandler (IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (SomeException -> IO a
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO SomeException
    e)) [Handler m a]
    handlers
        where tryHandler :: Handler m a -> m a -> m a
    tryHandler (Handler handler :: e -> m a
    handler) res :: m a
    res
                  = case SomeException -> Maybe e
    forall e. Exception e => SomeException -> Maybe e
    fromException SomeException
    e of
                    Just e' :: e
    e' -> e -> m a
    handler e
    e'
                    Nothing -> m a
    res

    -- | Same as upstream 'EUnsafe.catches', but will not catch
    -- asynchronous exceptions.
    --
    -- @since 0.1.0.0
    catches :: MonadUnliftIO m => m a -> [Handler m a] -> m a
    catches :: m a -> [Handler m a] -> m a
    catches io :: m a
    io handlers :: [Handler m a]
    handlers = m a
    io m a -> (SomeException -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    `catch` [Handler m a] -> SomeException -> m a
    forall (m :: * -> *) a.
    MonadIO m =>
    [Handler m a] -> SomeException -> m a
    catchesHandler [Handler m a]
    handlers

    -- | Same as 'catches', but fully force evaluation of the result value
    -- to find all impure exceptions.
    --
    -- @since 0.1.0.0
    catchesDeep :: (MonadUnliftIO m, NFData a) => m a -> [Handler m a] -> m a
    catchesDeep :: m a -> [Handler m a] -> m a
    catchesDeep io :: m a
    io handlers :: [Handler m a]
    handlers = (m a
    io m a -> (a -> m a) -> m a
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> m a
    forall (m :: * -> *) a. (MonadIO m, NFData a) => a -> m a
    evaluateDeep) m a -> (SomeException -> m a) -> m a
    forall (m :: * -> *) e a.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m a) -> m a
    `catch` [Handler m a] -> SomeException -> m a
    forall (m :: * -> *) a.
    MonadIO m =>
    [Handler m a] -> SomeException -> m a
    catchesHandler [Handler m a]
    handlers

    -- | Lifted version of 'EUnsafe.evaluate'.
    --
    -- @since 0.1.0.0
    evaluate :: MonadIO m => a -> m a
    evaluate :: a -> m a
    evaluate = IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> (a -> IO a) -> a -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> IO a
    forall a. a -> IO a
    EUnsafe.evaluate

    -- | Deeply evaluate a value using 'evaluate' and 'NFData'.
    --
    -- @since 0.1.0.0
    evaluateDeep :: (MonadIO m, NFData a) => a -> m a
    evaluateDeep :: a -> m a
    evaluateDeep = (a -> m a
    forall (m :: * -> *) a. MonadIO m => a -> m a
    evaluate (a -> m a) -> a -> m a
    forall a b. NFData a => (a -> b) -> a -> b
    $!!)

    -- | Async safe version of 'EUnsafe.bracket'.
    --
    -- @since 0.1.0.0
    bracket :: MonadUnliftIO m => m a -> (a -> m b) -> (a -> m c) -> m c
    bracket :: m a -> (a -> m b) -> (a -> m c) -> m c
    bracket before :: m a
    before after :: a -> m b
    after thing :: a -> m c
    thing = ((forall a. m a -> IO a) -> IO c) -> m c
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO c) -> m c)
    -> ((forall a. m a -> IO a) -> IO c) -> m c
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO c) -> IO c
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    EUnsafe.mask (((forall a. IO a -> IO a) -> IO c) -> IO c)
    -> ((forall a. IO a -> IO a) -> IO c) -> IO c
    forall a b. (a -> b) -> a -> b
    $ \restore :: forall a. IO a -> IO a
    restore -> do
      a
    x <- m a -> IO a
    forall a. m a -> IO a
    run m a
    before
      Either SomeException c
    res1 <- IO c -> IO (Either SomeException c)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO c -> IO (Either SomeException c))
    -> IO c -> IO (Either SomeException c)
    forall a b. (a -> b) -> a -> b
    $ IO c -> IO c
    forall a. IO a -> IO a
    restore (IO c -> IO c) -> IO c -> IO c
    forall a b. (a -> b) -> a -> b
    $ m c -> IO c
    forall a. m a -> IO a
    run (m c -> IO c) -> m c -> IO c
    forall a b. (a -> b) -> a -> b
    $ a -> m c
    thing a
    x
      case Either SomeException c
    res1 of
        Left (SomeException
    e1 :: SomeException) -> do
          -- explicitly ignore exceptions from after. We know that
          -- no async exceptions were thrown there, so therefore
          -- the stronger exception must come from thing
          --
          -- https://github.com/fpco/safe-exceptions/issues/2
          Either SomeException b
    _ :: Either SomeException b <-
              IO b -> IO (Either SomeException b)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO b -> IO (Either SomeException b))
    -> IO b -> IO (Either SomeException b)
    forall a b. (a -> b) -> a -> b
    $ IO b -> IO b
    forall a. IO a -> IO a
    EUnsafe.uninterruptibleMask_ (IO b -> IO b) -> IO b -> IO b
    forall a b. (a -> b) -> a -> b
    $ m b -> IO b
    forall a. m a -> IO a
    run (m b -> IO b) -> m b -> IO b
    forall a b. (a -> b) -> a -> b
    $ a -> m b
    after a
    x
          SomeException -> IO c
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO SomeException
    e1
        Right y :: c
    y -> do
          b
    _ <- IO b -> IO b
    forall a. IO a -> IO a
    EUnsafe.uninterruptibleMask_ (IO b -> IO b) -> IO b -> IO b
    forall a b. (a -> b) -> a -> b
    $ m b -> IO b
    forall a. m a -> IO a
    run (m b -> IO b) -> m b -> IO b
    forall a b. (a -> b) -> a -> b
    $ a -> m b
    after a
    x
          c -> IO c
    forall (m :: * -> *) a. Monad m => a -> m a
    return c
    y

    -- | Async safe version of 'EUnsafe.bracket_'.
    --
    -- @since 0.1.0.0
    bracket_ :: MonadUnliftIO m => m a -> m b -> m c -> m c
    bracket_ :: m a -> m b -> m c -> m c
    bracket_ before :: m a
    before after :: m b
    after thing :: m c
    thing = m a -> (a -> m b) -> (a -> m c) -> m c
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    m a -> (a -> m b) -> (a -> m c) -> m c
    bracket m a
    before (m b -> a -> m b
    forall a b. a -> b -> a
    const m b
    after) (m c -> a -> m c
    forall a b. a -> b -> a
    const m c
    thing)

    -- | Async safe version of 'EUnsafe.bracketOnError'.
    --
    -- @since 0.1.0.0
    bracketOnError :: MonadUnliftIO m => m a -> (a -> m b) -> (a -> m c) -> m c
    bracketOnError :: m a -> (a -> m b) -> (a -> m c) -> m c
    bracketOnError before :: m a
    before after :: a -> m b
    after thing :: a -> m c
    thing = ((forall a. m a -> IO a) -> IO c) -> m c
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO c) -> m c)
    -> ((forall a. m a -> IO a) -> IO c) -> m c
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO c) -> IO c
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    EUnsafe.mask (((forall a. IO a -> IO a) -> IO c) -> IO c)
    -> ((forall a. IO a -> IO a) -> IO c) -> IO c
    forall a b. (a -> b) -> a -> b
    $ \restore :: forall a. IO a -> IO a
    restore -> do
      a
    x <- m a -> IO a
    forall a. m a -> IO a
    run m a
    before
      Either SomeException c
    res1 <- IO c -> IO (Either SomeException c)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO c -> IO (Either SomeException c))
    -> IO c -> IO (Either SomeException c)
    forall a b. (a -> b) -> a -> b
    $ IO c -> IO c
    forall a. IO a -> IO a
    restore (IO c -> IO c) -> IO c -> IO c
    forall a b. (a -> b) -> a -> b
    $ m c -> IO c
    forall a. m a -> IO a
    run (m c -> IO c) -> m c -> IO c
    forall a b. (a -> b) -> a -> b
    $ a -> m c
    thing a
    x
      case Either SomeException c
    res1 of
        Left (SomeException
    e1 :: SomeException) -> do
          -- ignore the exception, see bracket for explanation
          Either SomeException b
    _ :: Either SomeException b <-
            IO b -> IO (Either SomeException b)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO b -> IO (Either SomeException b))
    -> IO b -> IO (Either SomeException b)
    forall a b. (a -> b) -> a -> b
    $ IO b -> IO b
    forall a. IO a -> IO a
    EUnsafe.uninterruptibleMask_ (IO b -> IO b) -> IO b -> IO b
    forall a b. (a -> b) -> a -> b
    $ m b -> IO b
    forall a. m a -> IO a
    run (m b -> IO b) -> m b -> IO b
    forall a b. (a -> b) -> a -> b
    $ a -> m b
    after a
    x
          SomeException -> IO c
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO SomeException
    e1
        Right y :: c
    y -> c -> IO c
    forall (m :: * -> *) a. Monad m => a -> m a
    return c
    y

    -- | A variant of 'bracketOnError' where the return value from the first
    -- computation is not required.
    --
    -- @since 0.1.0.0
    bracketOnError_ :: MonadUnliftIO m => m a -> m b -> m c -> m c
    bracketOnError_ :: m a -> m b -> m c -> m c
    bracketOnError_ before :: m a
    before after :: m b
    after thing :: m c
    thing = m a -> (a -> m b) -> (a -> m c) -> m c
    forall (m :: * -> *) a b c.
    MonadUnliftIO m =>
    m a -> (a -> m b) -> (a -> m c) -> m c
    bracketOnError m a
    before (m b -> a -> m b
    forall a b. a -> b -> a
    const m b
    after) (m c -> a -> m c
    forall a b. a -> b -> a
    const m c
    thing)

    -- | Async safe version of 'EUnsafe.finally'.
    --
    -- @since 0.1.0.0
    finally :: MonadUnliftIO m => m a -> m b -> m a
    finally :: m a -> m b -> m a
    finally thing :: m a
    thing after :: m b
    after = ((forall a. m a -> IO a) -> IO a) -> m a
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO a) -> m a)
    -> ((forall a. m a -> IO a) -> IO a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO a) -> IO a
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    EUnsafe.uninterruptibleMask (((forall a. IO a -> IO a) -> IO a) -> IO a)
    -> ((forall a. IO a -> IO a) -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \restore :: forall a. IO a -> IO a
    restore -> do
      Either SomeException a
    res1 <- IO a -> IO (Either SomeException a)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO a -> IO (Either SomeException a))
    -> IO a -> IO (Either SomeException a)
    forall a b. (a -> b) -> a -> b
    $ IO a -> IO a
    forall a. IO a -> IO a
    restore (IO a -> IO a) -> IO a -> IO a
    forall a b. (a -> b) -> a -> b
    $ m a -> IO a
    forall a. m a -> IO a
    run m a
    thing
      case Either SomeException a
    res1 of
        Left (SomeException
    e1 :: SomeException) -> do
          -- see bracket for explanation
          Either SomeException b
    _ :: Either SomeException b <- IO b -> IO (Either SomeException b)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO b -> IO (Either SomeException b))
    -> IO b -> IO (Either SomeException b)
    forall a b. (a -> b) -> a -> b
    $ m b -> IO b
    forall a. m a -> IO a
    run m b
    after
          SomeException -> IO a
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO SomeException
    e1
        Right x :: a
    x -> do
          b
    _ <- m b -> IO b
    forall a. m a -> IO a
    run m b
    after
          a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x

    -- | Like 'onException', but provides the handler the thrown
    -- exception.
    --
    -- @since 0.1.0.0
    withException :: (MonadUnliftIO m, Exception e)
                  => m a -> (e -> m b) -> m a
    withException :: m a -> (e -> m b) -> m a
    withException thing :: m a
    thing after :: e -> m b
    after = ((forall a. m a -> IO a) -> IO a) -> m a
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO a) -> m a)
    -> ((forall a. m a -> IO a) -> IO a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO a) -> IO a
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    EUnsafe.uninterruptibleMask (((forall a. IO a -> IO a) -> IO a) -> IO a)
    -> ((forall a. IO a -> IO a) -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \restore :: forall a. IO a -> IO a
    restore -> do
        Either e a
    res1 <- IO a -> IO (Either e a)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO a -> IO (Either e a)) -> IO a -> IO (Either e a)
    forall a b. (a -> b) -> a -> b
    $ IO a -> IO a
    forall a. IO a -> IO a
    restore (IO a -> IO a) -> IO a -> IO a
    forall a b. (a -> b) -> a -> b
    $ m a -> IO a
    forall a. m a -> IO a
    run m a
    thing
        case Either e a
    res1 of
            Left e1 :: e
    e1 -> do
                -- see explanation in bracket
                Either SomeException b
    _ :: Either SomeException b <- IO b -> IO (Either SomeException b)
    forall e a. Exception e => IO a -> IO (Either e a)
    EUnsafe.try (IO b -> IO (Either SomeException b))
    -> IO b -> IO (Either SomeException b)
    forall a b. (a -> b) -> a -> b
    $ m b -> IO b
    forall a. m a -> IO a
    run (m b -> IO b) -> m b -> IO b
    forall a b. (a -> b) -> a -> b
    $ e -> m b
    after e
    e1
                e -> IO a
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO e
    e1
            Right x :: a
    x -> a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x

    -- | Async safe version of 'EUnsafe.onException'.
    --
    -- @since 0.1.0.0
    onException :: MonadUnliftIO m => m a -> m b -> m a
    onException :: m a -> m b -> m a
    onException thing :: m a
    thing after :: m b
    after = m a -> (SomeException -> m b) -> m a
    forall (m :: * -> *) e a b.
    (MonadUnliftIO m, Exception e) =>
    m a -> (e -> m b) -> m a
    withException m a
    thing (\(SomeException
    _ :: SomeException) -> m b
    after)

    -- | Synchronously throw the given exception.
    --
    -- @since 0.1.0.0
    throwIO :: (MonadIO m, Exception e) => e -> m a
    throwIO :: e -> m a
    throwIO = IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> (e -> IO a) -> e -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SomeException -> IO a
    forall e a. Exception e => e -> IO a
    EUnsafe.throwIO (SomeException -> IO a) -> (e -> SomeException) -> e -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> SomeException
    forall e. Exception e => e -> SomeException
    toSyncException

    -- | Wrap up an asynchronous exception to be treated as a synchronous
    -- exception.
    --
    -- This is intended to be created via 'toSyncException'.
    --
    -- @since 0.1.0.0
    data SyncExceptionWrapper = forall e. Exception e => SyncExceptionWrapper e
        deriving Typeable
    -- | @since 0.1.0.0
    instance Show SyncExceptionWrapper where
        show :: SyncExceptionWrapper -> String
    show (SyncExceptionWrapper e :: e
    e) = e -> String
    forall a. Show a => a -> String
    show e
    e
    -- | @since 0.1.0.0
    instance Exception SyncExceptionWrapper where
    #if MIN_VERSION_base(4,8,0)
        displayException :: SyncExceptionWrapper -> String
    displayException (SyncExceptionWrapper e :: e
    e) = e -> String
    forall e. Exception e => e -> String
    displayException e
    e
    #endif

    -- | Convert an exception into a synchronous exception.
    --
    -- For synchronous exceptions, this is the same as 'toException'.
    -- For asynchronous exceptions, this will wrap up the exception with
    -- 'SyncExceptionWrapper'.
    --
    -- @since 0.1.0.0
    toSyncException :: Exception e => e -> SomeException
    toSyncException :: e -> SomeException
    toSyncException e :: e
    e =
        case SomeException -> Maybe SomeAsyncException
    forall e. Exception e => SomeException -> Maybe e
    fromException SomeException
    se of
            Just (SomeAsyncException _) -> SyncExceptionWrapper -> SomeException
    forall e. Exception e => e -> SomeException
    toException (e -> SyncExceptionWrapper
    forall e. Exception e => e -> SyncExceptionWrapper
    SyncExceptionWrapper e
    e)
            Nothing -> SomeException
    se
      where
        se :: SomeException
    se = e -> SomeException
    forall e. Exception e => e -> SomeException
    toException e
    e

    -- | Wrap up a synchronous exception to be treated as an asynchronous
    -- exception.
    --
    -- This is intended to be created via 'toAsyncException'.
    --
    -- @since 0.1.0.0
    data AsyncExceptionWrapper = forall e. Exception e => AsyncExceptionWrapper e
        deriving Typeable
    -- | @since 0.1.0.0
    instance Show AsyncExceptionWrapper where
        show :: AsyncExceptionWrapper -> String
    show (AsyncExceptionWrapper e :: e
    e) = e -> String
    forall a. Show a => a -> String
    show e
    e
    -- | @since 0.1.0.0
    instance Exception AsyncExceptionWrapper where
        toException :: AsyncExceptionWrapper -> SomeException
    toException = SomeAsyncException -> SomeException
    forall e. Exception e => e -> SomeException
    toException (SomeAsyncException -> SomeException)
    -> (AsyncExceptionWrapper -> SomeAsyncException)
    -> AsyncExceptionWrapper
    -> SomeException
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . AsyncExceptionWrapper -> SomeAsyncException
    forall e. Exception e => e -> SomeAsyncException
    SomeAsyncException
        fromException :: SomeException -> Maybe AsyncExceptionWrapper
    fromException se :: SomeException
    se = do
            SomeAsyncException e :: e
    e <- SomeException -> Maybe SomeAsyncException
    forall e. Exception e => SomeException -> Maybe e
    fromException SomeException
    se
            e -> Maybe AsyncExceptionWrapper
    forall a b. (Typeable a, Typeable b) => a -> Maybe b
    cast e
    e
    #if MIN_VERSION_base(4,8,0)
        displayException :: AsyncExceptionWrapper -> String
    displayException (AsyncExceptionWrapper e :: e
    e) = e -> String
    forall e. Exception e => e -> String
    displayException e
    e
    #endif

    -- | Convert an exception into an asynchronous exception.
    --
    -- For asynchronous exceptions, this is the same as 'toException'.
    -- For synchronous exceptions, this will wrap up the exception with
    -- 'AsyncExceptionWrapper'.
    --
    -- @since 0.1.0.0
    toAsyncException :: Exception e => e -> SomeException
    toAsyncException :: e -> SomeException
    toAsyncException e :: e
    e =
        case SomeException -> Maybe SomeAsyncException
    forall e. Exception e => SomeException -> Maybe e
    fromException SomeException
    se of
            Just (SomeAsyncException _) -> SomeException
    se
            Nothing -> AsyncExceptionWrapper -> SomeException
    forall e. Exception e => e -> SomeException
    toException (e -> AsyncExceptionWrapper
    forall e. Exception e => e -> AsyncExceptionWrapper
    AsyncExceptionWrapper e
    e)
      where
        se :: SomeException
    se = e -> SomeException
    forall e. Exception e => e -> SomeException
    toException e
    e

    -- | Check if the given exception is synchronous.
    --
    -- @since 0.1.0.0
    isSyncException :: Exception e => e -> Bool
    isSyncException :: e -> Bool
    isSyncException e :: e
    e =
        case SomeException -> Maybe SomeAsyncException
    forall e. Exception e => SomeException -> Maybe e
    fromException (e -> SomeException
    forall e. Exception e => e -> SomeException
    toException e
    e) of
            Just (SomeAsyncException _) -> Bool
    False
            Nothing -> Bool
    True

    -- | Check if the given exception is asynchronous.
    --
    -- @since 0.1.0.0
    isAsyncException :: Exception e => e -> Bool
    isAsyncException :: e -> Bool
    isAsyncException = Bool -> Bool
    not (Bool -> Bool) -> (e -> Bool) -> e -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> Bool
    forall e. Exception e => e -> Bool
    isSyncException
    {-# INLINE isAsyncException #-}

    #if !MIN_VERSION_base(4,8,0)
    -- | A synonym for 'show', specialized to 'Exception' instances.
    --
    -- Starting with base 4.8, the 'Exception' typeclass has a method
    -- @displayException@, used for user-friendly display of exceptions.
    -- This function provides backwards compatibility for users on base 4.7 and earlier,
    -- so that anyone importing this module can simply use @displayException@.
    --
    -- @since 0.1.0.0
    displayException :: Exception e => e -> String
    displayException = show
    #endif

    -- | Unlifted version of 'EUnsafe.mask'.
    --
    -- @since 0.1.0.0
    mask :: MonadUnliftIO m => ((forall a. m a -> m a) -> m b) -> m b
    mask :: ((forall a. m a -> m a) -> m b) -> m b
    mask f :: (forall a. m a -> m a) -> m b
    f = ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO b) -> m b)
    -> ((forall a. m a -> IO a) -> IO b) -> m b
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO b) -> IO b
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    EUnsafe.mask (((forall a. IO a -> IO a) -> IO b) -> IO b)
    -> ((forall a. IO a -> IO a) -> IO b) -> IO b
    forall a b. (a -> b) -> a -> b
    $ \unmask :: forall a. IO a -> IO a
    unmask ->
      m b -> IO b
    forall a. m a -> IO a
    run (m b -> IO b) -> m b -> IO b
    forall a b. (a -> b) -> a -> b
    $ (forall a. m a -> m a) -> m b
    f ((forall a. m a -> m a) -> m b) -> (forall a. m a -> m a) -> m b
    forall a b. (a -> b) -> a -> b
    $ IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> (m a -> IO a) -> m a -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO a -> IO a
    forall a. IO a -> IO a
    unmask (IO a -> IO a) -> (m a -> IO a) -> m a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . m a -> IO a
    forall a. m a -> IO a
    run

    -- | Unlifted version of 'EUnsafe.uninterruptibleMask'.
    --
    -- @since 0.1.0.0
    uninterruptibleMask :: MonadUnliftIO m => ((forall a. m a -> m a) -> m b) -> m b
    uninterruptibleMask :: ((forall a. m a -> m a) -> m b) -> m b
    uninterruptibleMask f :: (forall a. m a -> m a) -> m b
    f = ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO b) -> m b)
    -> ((forall a. m a -> IO a) -> IO b) -> m b
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO b) -> IO b
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    EUnsafe.uninterruptibleMask (((forall a. IO a -> IO a) -> IO b) -> IO b)
    -> ((forall a. IO a -> IO a) -> IO b) -> IO b
    forall a b. (a -> b) -> a -> b
    $ \unmask :: forall a. IO a -> IO a
    unmask ->
      m b -> IO b
    forall a. m a -> IO a
    run (m b -> IO b) -> m b -> IO b
    forall a b. (a -> b) -> a -> b
    $ (forall a. m a -> m a) -> m b
    f ((forall a. m a -> m a) -> m b) -> (forall a. m a -> m a) -> m b
    forall a b. (a -> b) -> a -> b
    $ IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> (m a -> IO a) -> m a -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO a -> IO a
    forall a. IO a -> IO a
    unmask (IO a -> IO a) -> (m a -> IO a) -> m a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . m a -> IO a
    forall a. m a -> IO a
    run

    -- | Unlifted version of 'EUnsafe.mask_'.
    --
    -- @since 0.1.0.0
    mask_ :: MonadUnliftIO m => m a -> m a
    mask_ :: m a -> m a
    mask_ f :: m a
    f = ((forall a. m a -> IO a) -> IO a) -> m a
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO a) -> m a)
    -> ((forall a. m a -> IO a) -> IO a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> IO a -> IO a
    forall a. IO a -> IO a
    EUnsafe.mask_ (m a -> IO a
    forall a. m a -> IO a
    run m a
    f)

    -- | Unlifted version of 'EUnsafe.uninterruptibleMask_'.
    --
    -- @since 0.1.0.0
    uninterruptibleMask_ :: MonadUnliftIO m => m a -> m a
    uninterruptibleMask_ :: m a -> m a
    uninterruptibleMask_ f :: m a
    f = ((forall a. m a -> IO a) -> IO a) -> m a
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO a) -> m a)
    -> ((forall a. m a -> IO a) -> IO a) -> m a
    forall a b. (a -> b) -> a -> b
    $ \run :: forall a. m a -> IO a
    run -> IO a -> IO a
    forall a. IO a -> IO a
    EUnsafe.uninterruptibleMask_ (m a -> IO a
    forall a. m a -> IO a
    run m a
    f)

    -- | A convenience function for throwing a user error. This is useful
    -- for cases where it would be too high a burden to define your own
    -- exception type.
    --
    -- This throws an exception of type 'StringException'. When GHC
    -- supports it (base 4.9 and GHC 8.0 and onward), it includes a call
    -- stack.
    --
    -- @since 0.1.0.0
    #if MIN_VERSION_base(4,9,0)
    throwString :: (MonadIO m, HasCallStack) => String -> m a
    throwString :: String -> m a
    throwString s :: String
    s = StringException -> m a
    forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
    throwIO (String -> CallStack -> StringException
    StringException String
    s ?callStack::CallStack
    CallStack
    ?callStack)
    #else
    throwString :: MonadIO m => String -> m a
    throwString s = throwIO (StringException s ())
    #endif

    -- | Smart constructor for a 'StringException' that deals with the
    -- call stack.
    --
    -- @since 0.1.0.0
    #if MIN_VERSION_base(4,9,0)
    stringException :: HasCallStack => String -> StringException
    stringException :: String -> StringException
    stringException s :: String
    s = String -> CallStack -> StringException
    StringException String
    s ?callStack::CallStack
    CallStack
    ?callStack
    #else
    stringException :: String -> StringException
    stringException s = StringException s ()
    #endif

    -- | Exception type thrown by 'throwString'.
    --
    -- Note that the second field of the data constructor depends on
    -- GHC/base version. For base 4.9 and GHC 8.0 and later, the second
    -- field is a call stack. Previous versions of GHC and base do not
    -- support call stacks, and the field is simply unit (provided to make
    -- pattern matching across GHC versions easier).
    --
    -- @since 0.1.0.0
    #if MIN_VERSION_base(4,9,0)
    data StringException = StringException String CallStack
      deriving Typeable

    -- | @since 0.1.0.0
    instance Show StringException where
        show :: StringException -> String
    show (StringException s :: String
    s cs :: CallStack
    cs) = [String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat
            ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ "UnliftIO.Exception.throwString called with:\n\n"
            String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : String
    s
            String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : "\nCalled from:\n"
            String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : ((String, SrcLoc) -> String) -> [(String, SrcLoc)] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map (String, SrcLoc) -> String
    go (CallStack -> [(String, SrcLoc)]
    getCallStack CallStack
    cs)
          where
            go :: (String, SrcLoc) -> String
    go (x :: String
    x, y :: SrcLoc
    y) = [String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat
              [ "  "
              , String
    x
              , " ("
              , SrcLoc -> String
    prettySrcLoc SrcLoc
    y
              , ")\n"
              ]
    #else
    data StringException = StringException String ()
      deriving Typeable

    -- | @since 0.1.0.0
    instance Show StringException where
        show (StringException s _) = "UnliftIO.Exception.throwString called with:\n\n" ++ s
    #endif

    -- | @since 0.1.0.0
    instance Exception StringException

    -- | Throw an asynchronous exception to another thread.
    --
    -- Synchronously typed exceptions will be wrapped into an
    -- `AsyncExceptionWrapper`, see
    -- <https://github.com/fpco/safe-exceptions#determining-sync-vs-async>.
    --
    -- It's usually a better idea to use the "UnliftIO.Async" module, see
    -- <https://github.com/fpco/safe-exceptions#quickstart>.
    --
    -- @since 0.1.0.0
    throwTo :: (Exception e, MonadIO m) => ThreadId -> e -> m ()
    throwTo :: ThreadId -> e -> m ()
    throwTo tid :: ThreadId
    tid = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (e -> IO ()) -> e -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ThreadId -> SomeException -> IO ()
    forall e. Exception e => ThreadId -> e -> IO ()
    EUnsafe.throwTo ThreadId
    tid (SomeException -> IO ()) -> (e -> SomeException) -> e -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> SomeException
    forall e. Exception e => e -> SomeException
    toAsyncException

    -- | Generate a pure value which, when forced, will synchronously
    -- throw the given exception.
    --
    -- Generally it's better to avoid using this function and instead use 'throwIO',
    -- see <https://github.com/fpco/safe-exceptions#quickstart>.
    --
    -- @since 0.1.0.0
    impureThrow :: Exception e => e -> a
    impureThrow :: e -> a
    impureThrow = SomeException -> a
    forall a e. Exception e => e -> a
    EUnsafe.throw (SomeException -> a) -> (e -> SomeException) -> e -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . e -> SomeException
    forall e. Exception e => e -> SomeException
    toSyncException

    -- | Unwrap an 'Either' value, throwing its 'Left' value as a runtime
    -- exception via 'throwIO' if present.
    --
    -- @since 0.1.0.0
    fromEither :: (Exception e, MonadIO m) => Either e a -> m a
    fromEither :: Either e a -> m a
    fromEither = (e -> m a) -> (a -> m a) -> Either e a -> m a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either e -> m a
    forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
    throwIO a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return

    -- | Same as 'fromEither', but works on an 'IO'-wrapped 'Either'.
    --
    -- @since 0.1.0.0
    fromEitherIO :: (Exception e, MonadIO m) => IO (Either e a) -> m a
    fromEitherIO :: IO (Either e a) -> m a
    fromEitherIO = m (Either e a) -> m a
    forall e (m :: * -> *) a.
    (Exception e, MonadIO m) =>
    m (Either e a) -> m a
    fromEitherM (m (Either e a) -> m a)
    -> (IO (Either e a) -> m (Either e a)) -> IO (Either e a) -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO (Either e a) -> m (Either e a)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO

    -- | Same as 'fromEither', but works on an 'm'-wrapped 'Either'.
    --
    -- @since 0.1.0.0
    fromEitherM :: (Exception e, MonadIO m) => m (Either e a) -> m a
    fromEitherM :: m (Either e a) -> m a
    fromEitherM = (m (Either e a) -> (Either e a -> m a) -> m a
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Either e a -> m a
    forall e (m :: * -> *) a.
    (Exception e, MonadIO m) =>
    Either e a -> m a
    fromEither)