Document exception handling in Actions/Rules (#3407)

* Document exception handling in Actions/Rules

I also took the liberty of removing the `MonadFail` instance for
`Rules`, since failing in `Rules` seems much worse as it won't
automatically be caught. There was only one use of that, which now has
an appropriately threatening comment.

* Tweak

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Michael Peyton Jones 2023-01-02 12:51:56 +00:00 committed by GitHub
parent 90d17fe1bc
commit 8f0d940445
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 3 deletions

View File

@ -307,13 +307,17 @@ type GetStalePersistent = NormalizedFilePath -> IdeAction (Maybe (Dynamic,Positi
getShakeExtras :: Action ShakeExtras
getShakeExtras = do
-- Will fail the action with a pattern match failure, but be caught
Just x <- getShakeExtra @ShakeExtras
return x
getShakeExtrasRules :: Rules ShakeExtras
getShakeExtrasRules = do
Just x <- getShakeExtraRules @ShakeExtras
return x
mExtras <- getShakeExtraRules @ShakeExtras
case mExtras of
Just x -> return x
-- This will actually crash HLS
Nothing -> liftIO $ fail "missing ShakeExtras"
-- | Returns the client configuration, creating a build dependency.
-- You should always use this function when accessing client configuration

View File

@ -54,8 +54,13 @@ unwrapDynamic x = fromMaybe (error msg) $ fromDynamic x
type TheRules = Map.HashMap TypeRep Dynamic
-- | A computation that defines all the rules that form part of the computation graph.
--
-- 'Rules' has access to 'IO' through 'MonadIO'. Use of 'IO' is at your own risk: if
-- you write 'Rules' that throw exceptions, then you need to make sure to handle them
-- yourself when you run the resulting 'Rules'.
newtype Rules a = Rules (ReaderT SRules IO a)
deriving newtype (Monad, Applicative, Functor, MonadIO, MonadFail)
deriving newtype (Monad, Applicative, Functor, MonadIO)
data SRules = SRules {
rulesExtra :: !Dynamic,
@ -67,6 +72,12 @@ data SRules = SRules {
---------------------------------------------------------------------
-- ACTIONS
-- | An action representing something that can be run as part of a 'Rule'.
--
-- 'Action's can be pure functions but also have access to 'IO' via 'MonadIO' and 'MonadUnliftIO.
-- It should be assumed that actions throw exceptions, these can be caught with
-- 'Development.IDE.Graph.Internal.Action.actionCatch'. In particular, it is
-- permissible to use the 'MonadFail' instance, which will lead to an 'IOException'.
newtype Action a = Action {fromAction :: ReaderT SAction IO a}
deriving newtype (Monad, Applicative, Functor, MonadIO, MonadFail, MonadThrow, MonadCatch, MonadMask, MonadUnliftIO)