summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorDavid Feuer <david.feuer@gmail.com>2017-11-02 12:06:56 -0400
committerBen Gamari <ben@smart-cactus.org>2017-11-02 13:20:26 -0400
commitb938576d151731b85314987fc550c17cfe824178 (patch)
tree3cda2f27bd490c45cfad3f231e1e0be183cb53a4 /libraries
parente0df569f7619dbef266139b9a6fa3ee9f632ea6e (diff)
downloadhaskell-b938576d151731b85314987fc550c17cfe824178.tar.gz
Add custom exception for fixIO
Traditionally, `fixIO f` throws `BlockedIndefinitelyOnMVar` if `f` is strict. This is not particularly friendly, since the `MVar` in question is just part of the way `fixIO` happens to be implemented. Instead, throw a new `FixIOException` with a better explanation of the problem. Reviewers: austin, hvr, bgamari Subscribers: rwbarton, thomie GHC Trac Issues: #14356 Differential Revision: https://phabricator.haskell.org/D4113
Diffstat (limited to 'libraries')
-rw-r--r--libraries/base/Control/Exception/Base.hs1
-rw-r--r--libraries/base/GHC/IO/Exception.hs10
-rw-r--r--libraries/base/System/IO.hs7
3 files changed, 17 insertions, 1 deletions
diff --git a/libraries/base/Control/Exception/Base.hs b/libraries/base/Control/Exception/Base.hs
index a15cc8ed32..d443159cb3 100644
--- a/libraries/base/Control/Exception/Base.hs
+++ b/libraries/base/Control/Exception/Base.hs
@@ -30,6 +30,7 @@ module Control.Exception.Base (
NonTermination(..),
NestedAtomically(..),
BlockedIndefinitelyOnMVar(..),
+ FixIOException (..),
BlockedIndefinitelyOnSTM(..),
AllocationLimitExceeded(..),
CompactionFailed(..),
diff --git a/libraries/base/GHC/IO/Exception.hs b/libraries/base/GHC/IO/Exception.hs
index 9203f46828..020bc067df 100644
--- a/libraries/base/GHC/IO/Exception.hs
+++ b/libraries/base/GHC/IO/Exception.hs
@@ -33,6 +33,7 @@ module GHC.IO.Exception (
ArrayException(..),
ExitCode(..),
+ FixIOException (..),
ioException,
ioError,
@@ -268,6 +269,15 @@ instance Show ArrayException where
. (if not (null s) then showString ": " . showString s
else id)
+-- | @since TODO
+data FixIOException = FixIOException
+
+-- | @since TODO
+instance Exception FixIOException
+
+instance Show FixIOException where
+ showsPrec _ FixIOException = showString "cyclic evaluation in fixIO"
+
-- -----------------------------------------------------------------------------
-- The ExitCode type
diff --git a/libraries/base/System/IO.hs b/libraries/base/System/IO.hs
index fde5bb66e5..68817247d2 100644
--- a/libraries/base/System/IO.hs
+++ b/libraries/base/System/IO.hs
@@ -400,10 +400,15 @@ withBinaryFile name mode = bracket (openBinaryFile name mode) hClose
-- ---------------------------------------------------------------------------
-- fixIO
+-- | The implementation of 'mfix' for 'IO'. If the function passed
+-- to 'fixIO' inspects its argument, the resulting action will throw
+-- 'FixIOException'.
fixIO :: (a -> IO a) -> IO a
fixIO k = do
m <- newEmptyMVar
- ans <- unsafeDupableInterleaveIO (readMVar m)
+ ans <- unsafeDupableInterleaveIO
+ (readMVar m `catch` \BlockedIndefinitelyOnMVar ->
+ throwIO FixIOException)
result <- k ans
putMVar m result
return result