Wolfgang Jeltsch pushed to branch wip/jeltsch/stm-exception-improvements at Glasgow Haskell Compiler / GHC Commits: 3731b23a by Wolfgang Jeltsch at 2026-08-12T17:20:52+03:00 Add `rethrowSTM` and improve STM-related documentation Adding `rethrowSTM` resolves #26758. The implementation of `rethrowSTM` is completely analogous to the one of `rethrowIO`. The following is established for the documentation of `throwSTM` and `catchSTM`: * Both operations are directly described as analogs of their `IO` counterparts. * There is no reference to `throw` in the documentation of `throwSTM`, because, although such a reference is great in the documentation of `throwIO`, it is somewhat out of place in the documentation of `throwSTM`. * Instead of repeating part of `throwIO`’s documentation, the documentation of `throwSTM` just recommends using `throwSTM` instead of `throw` and references the corresponding arguments in the documentation of `throwIO`. - - - - - 6 changed files: - + changelog.d/rethrow-stm - libraries/base/src/GHC/Conc.hs - libraries/ghc-internal/src/GHC/Internal/STM.hs - testsuite/tests/interface-stability/base-exports.stdout - testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs - testsuite/tests/interface-stability/base-exports.stdout-mingw32 Changes: ===================================== changelog.d/rethrow-stm ===================================== @@ -0,0 +1,4 @@ +section: ghc-internal +synopsis: Add `rethrowSTM`, an `STM` analog of `rethrowIO` +issues: #26758 +mrs: !16501 ===================================== libraries/base/src/GHC/Conc.hs ===================================== @@ -79,6 +79,9 @@ module GHC.Conc , retry , orElse , throwSTM +#if __GLASGOW_HASKELL__ >= 1000 + , rethrowSTM +#endif , catchSTM , TVar(..) , newTVar ===================================== libraries/ghc-internal/src/GHC/Internal/STM.hs ===================================== @@ -3,6 +3,7 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} +{-# OPTIONS_GHC -Wno-unused-imports #-} {-# OPTIONS_HADDOCK not-home #-} module GHC.Internal.STM @@ -13,6 +14,7 @@ module GHC.Internal.STM , retry , orElse , throwSTM + , rethrowSTM , catchSTM , unsafeIOToSTM -- * TVars @@ -31,7 +33,9 @@ import GHC.Internal.Base ( import GHC.Internal.Classes (Eq(..)) import GHC.Internal.Exception (Exception, toExceptionWithBacktrace, fromException, addExceptionContext) import GHC.Internal.Exception.Context (ExceptionAnnotation) -import GHC.Internal.Exception.Type (WhileHandling(..)) +import GHC.Internal.Exception.Type ( + WhileHandling(..), ExceptionWithContext, NoBacktrace (NoBacktrace), + ) import GHC.Internal.Maybe (Maybe(..)) import GHC.Internal.Prim ( RealWorld, State#, TVar#, atomically#, catch#, catchRetry#, catchSTM#, @@ -41,6 +45,10 @@ import GHC.Internal.Prim.PtrEq (sameTVar#) import GHC.Internal.Stack (HasCallStack, withFrozenCallStack) import GHC.Internal.Types (IO(..), isTrue#) +-- Imports for documentation hyperlinking +import GHC.Internal.Exception (throw) +import GHC.Internal.IO (throwIO, rethrowIO) + -- TVars are shared memory locations which support atomic memory -- transactions. @@ -170,7 +178,7 @@ retry = STM $ \s# -> retry# s# orElse :: STM a -> STM a -> STM a orElse (STM m) e = STM $ \s -> catchRetry# m (unSTM e) s --- | A variant of 'throw' that can only be used within the 'STM' monad. +-- | The 'STM' analog of 'throwIO'. -- -- Throwing an exception in @STM@ aborts the transaction and propagates the -- exception. If the exception is caught via 'catchSTM', only the changes @@ -180,19 +188,8 @@ orElse (STM m) e = STM $ \s -> catchRetry# m (unSTM e) s -- If the exception is not caught inside of the 'STM', it is re-thrown by -- 'atomically', and the entire 'STM' is rolled back. -- --- Although 'throwSTM' has a type that is an instance of the type of 'throw', the --- two functions are subtly different: --- --- > throw e `seq` x ===> throw e --- > throwSTM e `seq` x ===> x --- --- The first example will cause the exception @e@ to be raised, --- whereas the second one won\'t. In fact, 'throwSTM' will only cause --- an exception to be raised when it is used within the 'STM' monad. --- The 'throwSTM' variant should be used in preference to 'throw' to --- raise an exception within the 'STM' monad because it guarantees --- ordering with respect to other 'STM' operations, whereas 'throw' --- does not. +-- Note that 'throwSTM' is preferable to 'throw', for the same reasons that +-- 'throwIO' is preferable to 'throw'. throwSTM :: (HasCallStack, Exception e) => e -> STM a throwSTM e = do -- N.B. Typically use of unsafeIOToSTM is very much frowned upon as this @@ -201,7 +198,11 @@ throwSTM e = do se <- unsafeIOToSTM (withFrozenCallStack $ toExceptionWithBacktrace e) STM $ raiseIO# se --- | Exception handling within STM actions. +-- | The 'STM' analog of 'rethrowIO'. +rethrowSTM :: Exception e => ExceptionWithContext e -> STM a +rethrowSTM e = throwSTM (NoBacktrace e) + +-- | The 'STM' analog of 'catch'. -- -- @'catchSTM' m f@ catches any exception thrown by @m@ using 'throwSTM', -- using the function @f@ to handle the exception. If an exception is ===================================== testsuite/tests/interface-stability/base-exports.stdout ===================================== @@ -5135,6 +5135,7 @@ module GHC.Conc where reportError :: GHC.Internal.Exception.Type.SomeException -> GHC.Internal.Types.IO () reportHeapOverflow :: GHC.Internal.Types.IO () reportStackOverflow :: GHC.Internal.Types.IO () + rethrowSTM :: forall e a. GHC.Internal.Exception.Type.Exception e => GHC.Internal.Exception.Type.ExceptionWithContext e -> STM a retry :: forall a. STM a runHandlers :: GHC.Internal.ForeignPtr.ForeignPtr GHC.Internal.Word.Word8 -> Signal -> GHC.Internal.Types.IO () runSparks :: GHC.Internal.Types.IO () ===================================== testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs ===================================== @@ -5135,6 +5135,7 @@ module GHC.Conc where reportError :: GHC.Internal.Exception.Type.SomeException -> GHC.Internal.Types.IO () reportHeapOverflow :: GHC.Internal.Types.IO () reportStackOverflow :: GHC.Internal.Types.IO () + rethrowSTM :: forall e a. GHC.Internal.Exception.Type.Exception e => GHC.Internal.Exception.Type.ExceptionWithContext e -> STM a retry :: forall a. STM a runHandlers :: GHC.Internal.ForeignPtr.ForeignPtr GHC.Internal.Word.Word8 -> Signal -> GHC.Internal.Types.IO () runSparks :: GHC.Internal.Types.IO () ===================================== testsuite/tests/interface-stability/base-exports.stdout-mingw32 ===================================== @@ -5141,6 +5141,7 @@ module GHC.Conc where reportError :: GHC.Internal.Exception.Type.SomeException -> GHC.Internal.Types.IO () reportHeapOverflow :: GHC.Internal.Types.IO () reportStackOverflow :: GHC.Internal.Types.IO () + rethrowSTM :: forall e a. GHC.Internal.Exception.Type.Exception e => GHC.Internal.Exception.Type.ExceptionWithContext e -> STM a retry :: forall a. STM a runSparks :: GHC.Internal.Types.IO () setAllocationCounter :: GHC.Internal.Int.Int64 -> GHC.Internal.Types.IO () View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3731b23a08216bbff8d7eadf8b380403... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3731b23a08216bbff8d7eadf8b380403... You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
participants (1)
-
Wolfgang Jeltsch (@jeltsch)