exceptions 0.10.6 → 0.10.7
raw patch · 3 files changed
+67/−33 lines, 3 filesdep −call-stackdep ~template-haskellPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: call-stack
Dependency ranges changed: template-haskell
API changes (from Hackage documentation)
- Control.Monad.Catch: bracket :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
+ Control.Monad.Catch: bracket :: HasCallStack => MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
- Control.Monad.Catch: bracketOnError :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b
+ Control.Monad.Catch: bracketOnError :: HasCallStack => MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
- Control.Monad.Catch: bracket_ :: (HasCallStack, MonadMask m) => m a -> m c -> m b -> m b
+ Control.Monad.Catch: bracket_ :: HasCallStack => MonadMask m => m a -> m c -> m b -> m b
- Control.Monad.Catch: catch :: (MonadCatch m, HasCallStack, Exception e) => m a -> (e -> m a) -> m a
+ Control.Monad.Catch: catch :: (MonadCatch m, HasCallStack) => Exception e => m a -> (e -> m a) -> m a
- Control.Monad.Catch: catchAll :: (HasCallStack, MonadCatch m) => m a -> (SomeException -> m a) -> m a
+ Control.Monad.Catch: catchAll :: HasCallStack => MonadCatch m => m a -> (SomeException -> m a) -> m a
- Control.Monad.Catch: catchIOError :: (HasCallStack, MonadCatch m) => m a -> (IOError -> m a) -> m a
+ Control.Monad.Catch: catchIOError :: HasCallStack => MonadCatch m => m a -> (IOError -> m a) -> m a
- Control.Monad.Catch: catchIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> m a -> (e -> m a) -> m a
+ Control.Monad.Catch: catchIf :: HasCallStack => (MonadCatch m, Exception e) => (e -> Bool) -> m a -> (e -> m a) -> m a
- Control.Monad.Catch: catchJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> (b -> m a) -> m a
+ Control.Monad.Catch: catchJust :: HasCallStack => (MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> (b -> m a) -> m a
- Control.Monad.Catch: catches :: (HasCallStack, Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
+ Control.Monad.Catch: catches :: HasCallStack => (Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
- Control.Monad.Catch: finally :: (HasCallStack, MonadMask m) => m a -> m b -> m a
+ Control.Monad.Catch: finally :: HasCallStack => MonadMask m => m a -> m b -> m a
- Control.Monad.Catch: handle :: (HasCallStack, MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
+ Control.Monad.Catch: handle :: HasCallStack => (MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
- Control.Monad.Catch: handleAll :: (HasCallStack, MonadCatch m) => (SomeException -> m a) -> m a -> m a
+ Control.Monad.Catch: handleAll :: HasCallStack => MonadCatch m => (SomeException -> m a) -> m a -> m a
- Control.Monad.Catch: handleIOError :: (HasCallStack, MonadCatch m) => (IOError -> m a) -> m a -> m a
+ Control.Monad.Catch: handleIOError :: HasCallStack => MonadCatch m => (IOError -> m a) -> m a -> m a
- Control.Monad.Catch: handleIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
+ Control.Monad.Catch: handleIf :: HasCallStack => (MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
- Control.Monad.Catch: handleJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
+ Control.Monad.Catch: handleJust :: HasCallStack => (MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
- Control.Monad.Catch: mask_ :: (HasCallStack, MonadMask m) => m a -> m a
+ Control.Monad.Catch: mask_ :: HasCallStack => MonadMask m => m a -> m a
- Control.Monad.Catch: onError :: (HasCallStack, MonadMask m) => m a -> m b -> m a
+ Control.Monad.Catch: onError :: HasCallStack => MonadMask m => m a -> m b -> m a
- Control.Monad.Catch: onException :: (HasCallStack, MonadCatch m) => m a -> m b -> m a
+ Control.Monad.Catch: onException :: HasCallStack => MonadCatch m => m a -> m b -> m a
- Control.Monad.Catch: throwM :: (MonadThrow m, HasCallStack, Exception e) => e -> m a
+ Control.Monad.Catch: throwM :: (MonadThrow m, HasCallStack) => Exception e => e -> m a
- Control.Monad.Catch: try :: (HasCallStack, MonadCatch m, Exception e) => m a -> m (Either e a)
+ Control.Monad.Catch: try :: HasCallStack => (MonadCatch m, Exception e) => m a -> m (Either e a)
- Control.Monad.Catch: tryJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
+ Control.Monad.Catch: tryJust :: HasCallStack => (MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
- Control.Monad.Catch: uninterruptibleMask_ :: (HasCallStack, MonadMask m) => m a -> m a
+ Control.Monad.Catch: uninterruptibleMask_ :: HasCallStack => MonadMask m => m a -> m a
Files
- CHANGELOG.markdown +13/−0
- exceptions.cabal +2/−3
- src/Control/Monad/Catch.hs +52/−30
CHANGELOG.markdown view
@@ -1,3 +1,16 @@+0.10.7 [2022.12.04] +------------------- +* On pre-8.0 GHCs, drop the `call-stack` dependency. This dependency was + introduced in `exceptions-0.10.6`, but it induced breakage in libraries + that derived instances of `MonadThrow`, `MonadCatch`, or `MonadMask` for + newtypes without first enabling `ConstraintKinds` and `FlexibleContexts`. + (Later versions of GHC do not require these language extensions for derived + instances, so only old GHCs were affected.) To avoid breakage, `exceptions` + no longer uses `HasCallStack` constraints on pre-8.0 versions of GHC. + + Note that `exceptions` still uses `HasCallStack` constraints on GHC 8.0 and + later, and as a result, these versions of GHC are unaffected by this change. + 0.10.6 [2022.11.30] ------------------- * The class methods and functions in `Control.Monad.Catch` now have
exceptions.cabal view
@@ -1,6 +1,6 @@ name: exceptions category: Control, Exceptions, Monad -version: 0.10.6 +version: 0.10.7 cabal-version: >= 1.10 license: BSD3 license-file: LICENSE @@ -51,8 +51,7 @@ mtl >= 2.0 && < 2.4 if !impl(ghc >= 8.0) - build-depends: call-stack >= 0.1 && < 0.5, - fail == 4.9.* + build-depends: fail == 4.9.* if flag(transformers-0-4) build-depends:
src/Control/Monad/Catch.hs view
@@ -1,7 +1,5 @@-{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ExistentialQuantification #-} -{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE FlexibleInstances #-} @@ -121,8 +119,6 @@ #if __GLASGOW_HASKELL__ >= 800 import GHC.Stack (HasCallStack, withFrozenCallStack) -#else -import Data.CallStack (HasCallStack) #endif #if !(MIN_VERSION_transformers(0,6,0)) @@ -130,7 +126,33 @@ import Control.Monad.Trans.List (ListT(..), runListT) #endif -#if __GLASGOW_HASKELL__ < 800 +-- We use the following bit of CPP to enable the use of HasCallStack +-- constraints without breaking the build for pre-8.0 GHCs, which did not +-- provide GHC.Stack. We are careful to always write constraints like this: +-- +-- HAS_CALL_STACK => MonadThrow m => ... +-- +-- Instead of like this: +-- +-- (HAS_CALL_STACK, MonadThrow e) => ... +-- +-- The latter is equivalent to (() :: Constraint, MonadThrow e) => ..., which +-- requires ConstraintKinds. More importantly, it's slightly less efficient, +-- since it requires passing an empty constraint tuple dictionary around. +-- +-- Note that we do /not/ depend on the call-stack compatibility library to +-- provide HasCallStack on older GHCs. We tried this at one point, but we +-- discovered that downstream libraries failed to build because combining +-- call-stack with GeneralizedNewtypeDeriving on older GHCs would require the +-- use of ConstraintKinds/FlexibleContexts, which downstream libraries did not +-- enable. (See #91.) The CPP approach that we use now, while somewhat clunky, +-- avoids these issues by not requiring any additional language extensions for +-- downstream users. +#if __GLASGOW_HASKELL__ >= 800 +# define HAS_CALL_STACK HasCallStack +#else +# define HAS_CALL_STACK () + withFrozenCallStack :: a -> a withFrozenCallStack a = a #endif @@ -156,7 +178,7 @@ -- Should satisfy the law: -- -- > throwM e >> f = throwM e - throwM :: (HasCallStack, Exception e) => e -> m a + throwM :: HAS_CALL_STACK => Exception e => e -> m a -- | A class for monads which allow exceptions to be caught, in particular -- exceptions which were thrown by 'throwM'. @@ -176,7 +198,7 @@ -- action. Note that type of the type of the argument to the handler will -- constrain which exceptions are caught. See "Control.Exception"'s -- 'ControlException.catch'. - catch :: (HasCallStack, Exception e) => m a -> (e -> m a) -> m a + catch :: HAS_CALL_STACK => Exception e => m a -> (e -> m a) -> m a -- | A class for monads which provide for the ability to account for -- all possible exit points from a computation, and to mask @@ -217,7 +239,7 @@ -- | Runs an action with asynchronous exceptions disabled. The action is -- provided a method for restoring the async. environment to what it was -- at the 'mask' call. See "Control.Exception"'s 'ControlException.mask'. - mask :: HasCallStack => ((forall a. m a -> m a) -> m b) -> m b + mask :: HAS_CALL_STACK => ((forall a. m a -> m a) -> m b) -> m b -- | Like 'mask', but the masked computation is not interruptible (see -- "Control.Exception"'s 'ControlException.uninterruptibleMask'. WARNING: @@ -225,7 +247,7 @@ -- AND you can guarantee the interruptible operation will only block for a -- short period of time. Otherwise you render the program/thread unresponsive -- and/or unkillable. - uninterruptibleMask :: HasCallStack => ((forall a. m a -> m a) -> m b) -> m b + uninterruptibleMask :: HAS_CALL_STACK => ((forall a. m a -> m a) -> m b) -> m b -- | A generalized version of 'bracket' which uses 'ExitCase' to distinguish -- the different exit cases, and returns the values of both the 'use' and @@ -318,7 +340,7 @@ -- -- @since 0.9.0 generalBracket - :: HasCallStack + :: HAS_CALL_STACK => m a -- ^ acquire some resource -> (a -> ExitCase b -> m c) @@ -747,12 +769,12 @@ ------------------------------------------------------------------------------ -- | Like 'mask', but does not pass a @restore@ action to the argument. -mask_ :: (HasCallStack, MonadMask m) => m a -> m a +mask_ :: HAS_CALL_STACK => MonadMask m => m a -> m a mask_ io = withFrozenCallStack (\f -> mask (\x -> f x)) (\_ -> io) -- | Like 'uninterruptibleMask', but does not pass a @restore@ action to the -- argument. -uninterruptibleMask_ :: (HasCallStack, MonadMask m) => m a -> m a +uninterruptibleMask_ :: HAS_CALL_STACK => MonadMask m => m a -> m a uninterruptibleMask_ io = withFrozenCallStack (\f -> uninterruptibleMask (\x -> f x)) (\_ -> io) -- | Catches all exceptions, and somewhat defeats the purpose of the extensible @@ -760,57 +782,57 @@ -- -- /NOTE/ This catches all /exceptions/, but if the monad supports other ways of -- aborting the computation, those other kinds of errors will not be caught. -catchAll :: (HasCallStack, MonadCatch m) => m a -> (SomeException -> m a) -> m a +catchAll :: HAS_CALL_STACK => MonadCatch m => m a -> (SomeException -> m a) -> m a catchAll = withFrozenCallStack catch -- | Catch all 'IOError' (eqv. 'IOException') exceptions. Still somewhat too -- general, but better than using 'catchAll'. See 'catchIf' for an easy way -- of catching specific 'IOError's based on the predicates in "System.IO.Error". -catchIOError :: (HasCallStack, MonadCatch m) => m a -> (IOError -> m a) -> m a +catchIOError :: HAS_CALL_STACK => MonadCatch m => m a -> (IOError -> m a) -> m a catchIOError = withFrozenCallStack catch -- | Catch exceptions only if they pass some predicate. Often useful with the -- predicates for testing 'IOError' values in "System.IO.Error". -catchIf :: (HasCallStack, MonadCatch m, Exception e) => +catchIf :: HAS_CALL_STACK => (MonadCatch m, Exception e) => (e -> Bool) -> m a -> (e -> m a) -> m a catchIf f a b = withFrozenCallStack catch a (\e -> if f e then b e else throwM e) -- | A more generalized way of determining which exceptions to catch at -- run time. -catchJust :: (HasCallStack, MonadCatch m, Exception e) => +catchJust :: HAS_CALL_STACK => (MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> (b -> m a) -> m a catchJust f a b = withFrozenCallStack catch a (\e -> maybe (throwM e) b $ f e) -- | Flipped 'catch'. See "Control.Exception"'s 'ControlException.handle'. -handle :: (HasCallStack, MonadCatch m, Exception e) => (e -> m a) -> m a -> m a +handle :: HAS_CALL_STACK => (MonadCatch m, Exception e) => (e -> m a) -> m a -> m a handle = flip (withFrozenCallStack catch) {-# INLINE handle #-} -- | Flipped 'catchIOError' -handleIOError :: (HasCallStack, MonadCatch m) => (IOError -> m a) -> m a -> m a +handleIOError :: HAS_CALL_STACK => MonadCatch m => (IOError -> m a) -> m a -> m a handleIOError = withFrozenCallStack handle -- | Flipped 'catchAll' -handleAll :: (HasCallStack, MonadCatch m) => (SomeException -> m a) -> m a -> m a +handleAll :: HAS_CALL_STACK => MonadCatch m => (SomeException -> m a) -> m a -> m a handleAll = withFrozenCallStack handle -- | Flipped 'catchIf' -handleIf :: (HasCallStack, MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a +handleIf :: HAS_CALL_STACK => (MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a handleIf f = flip (withFrozenCallStack catchIf f) -- | Flipped 'catchJust'. See "Control.Exception"'s 'ControlException.handleJust'. -handleJust :: (HasCallStack, MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a +handleJust :: HAS_CALL_STACK => (MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a handleJust f = flip (withFrozenCallStack catchJust f) {-# INLINE handleJust #-} -- | Similar to 'catch', but returns an 'Either' result. See "Control.Exception"'s -- 'Control.Exception.try'. -try :: (HasCallStack, MonadCatch m, Exception e) => m a -> m (Either e a) +try :: HAS_CALL_STACK => (MonadCatch m, Exception e) => m a -> m (Either e a) try a = withFrozenCallStack catch (Right `liftM` a) (return . Left) -- | A variant of 'try' that takes an exception predicate to select -- which exceptions are caught. See "Control.Exception"'s 'ControlException.tryJust' -tryJust :: (HasCallStack, MonadCatch m, Exception e) => +tryJust :: HAS_CALL_STACK => (MonadCatch m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a) tryJust f a = withFrozenCallStack catch (Right `liftM` a) (\e -> maybe (throwM e) (return . Left) (f e)) @@ -821,7 +843,7 @@ fmap f (Handler h) = Handler (liftM f . h) -- | Catches different sorts of exceptions. See "Control.Exception"'s 'ControlException.catches' -catches :: (HasCallStack, Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a +catches :: HAS_CALL_STACK => (Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a catches a hs = withFrozenCallStack catch a handler where handler e = foldr probe (throwM e) hs @@ -834,7 +856,7 @@ -- /NOTE/ The action is only run if an /exception/ is thrown. If the monad -- supports other ways of aborting the computation, the action won't run if -- those other kinds of errors are thrown. See 'onError'. -onException :: (HasCallStack, MonadCatch m) => m a -> m b -> m a +onException :: HAS_CALL_STACK => MonadCatch m => m a -> m b -> m a onException action handler = withFrozenCallStack catchAll action (\e -> handler >> throwM e) -- | Run an action only if an error is thrown in the main action. Unlike @@ -848,7 +870,7 @@ -- except that 'onError' has a more constrained type. -- -- @since 0.10.0 -onError :: (HasCallStack, MonadMask m) => m a -> m b -> m a +onError :: HAS_CALL_STACK => MonadMask m => m a -> m b -> m a onError action handler = withFrozenCallStack bracketOnError (return ()) (const handler) (const action) -- | Generalized abstracted pattern of safe resource acquisition and release @@ -864,24 +886,24 @@ -- signature from "Control.Exception"), and is often more convenient to use. By -- contrast, 'generalBracket' is more expressive, allowing us to implement -- other functions like 'bracketOnError'. -bracket :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b +bracket :: HAS_CALL_STACK => MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b bracket acquire release = liftM fst . withFrozenCallStack generalBracket acquire (\a _exitCase -> release a) -- | Version of 'bracket' without any value being passed to the second and -- third actions. -bracket_ :: (HasCallStack, MonadMask m) => m a -> m c -> m b -> m b +bracket_ :: HAS_CALL_STACK => MonadMask m => m a -> m c -> m b -> m b bracket_ before after action = withFrozenCallStack bracket before (const after) (const action) -- | Perform an action with a finalizer action that is run, even if an -- error occurs. -finally :: (HasCallStack, MonadMask m) => m a -> m b -> m a +finally :: HAS_CALL_STACK => MonadMask m => m a -> m b -> m a finally action finalizer = withFrozenCallStack bracket_ (return ()) finalizer action -- | Like 'bracket', but only performs the final action if an error is -- thrown by the in-between computation. -bracketOnError :: (HasCallStack, MonadMask m) => m a -> (a -> m c) -> (a -> m b) -> m b +bracketOnError :: HAS_CALL_STACK => MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b bracketOnError acquire release = liftM fst . withFrozenCallStack generalBracket acquire (\a exitCase -> case exitCase of