[Git][ghc/ghc][wip/T27022] iserv: recover/getQ/putQ should behave same as internal interpreter
Teo Camarasu pushed to branch wip/T27022 at Glasgow Haskell Compiler / GHC Commits: 9369b573 by Teo Camarasu at 2026-05-02T12:17:42+01:00 iserv: recover/getQ/putQ should behave same as internal interpreter The internal and external interpreter should behave the same when handling `recover`, the exeception recovery method of Q. In practice, they diverge. In case of failure, the internal interpreter only restores error message state to before the computation, wheras the external interperter restores error message state *and* the state of putQ/getQ. As far as I can tell this is a simple mistake in the implementation. Note [TH recover with -fexternal-interpreter] describes the correct behaviour but the implementation doesn't mirror this. This change restores the correct behaviour by keeping the effects of putQ in the erroring computation. This is a breaking change since it modifies the behaviour of programs that rely on recover ignoring putQ from failling computations when used with the external interpreter. Although I highly doubt anyone relies on this behaviour. Resolves #27022 - - - - - 4 changed files: - + changelog.d/T27022 - libraries/ghci/GHCi/TH.hs - + testsuite/tests/th/T27022.hs - testsuite/tests/th/all.T Changes: ===================================== changelog.d/T27022 ===================================== @@ -0,0 +1,11 @@ +section: compiler +synopsis: Fix a divergence in the interaction between ``recover`` and ``putQ`` between the internal and external interpreter +description: The ``recover`` method in TemplateHaskell now behaves the same + with the internal and external interpreter. + In the past, when an error was encountered in a computation in a ``recover`` block, + the external interpreter would discard any state changes from ``putQ``, + whereas the internal interpreter would not. + This was a long-standing error in the implementation of the external interpreter. + Both now keep state changes from ``putQ`` in ``recover`` blocks. +mr: !15994 +issues: #27022 ===================================== libraries/ghci/GHCi/TH.hs ===================================== @@ -175,9 +175,7 @@ instance TH.Quasi GHCiQ where e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) sRef remoteTHCall (qsPipe s) (EndRecover (isLeft e)) case e of - Left GHCiQException{} -> - -- in case of error, restore the state to the start of the `recover` block. - newIORef s >>= h + Left GHCiQException{} -> h sRef Right r -> return r qLookupName isType occ = ghcCmd (LookupName isType occ) qReify name = ghcCmd (Reify name) ===================================== testsuite/tests/th/T27022.hs ===================================== @@ -0,0 +1,8 @@ +{-# LANGUAGE TemplateHaskell #-} +-- | This tests the behaviour of TH's recover method. +-- It should behave the same in the internal and external interperter. +-- In the past, they have diverged, and the external interpreter would roll back the state of putQ/getQ whereas the internal interpreter would not. +module T27022 where + +import Language.Haskell.TH.Syntax +main = print $(putQ "0" >> recover (pure ()) (putQ "42" >> fail "oops") >> getQ @String >>= lift ) ===================================== testsuite/tests/th/all.T ===================================== @@ -650,3 +650,4 @@ test('GadtConSigs_th_dump1', normal, compile, ['-v0 -ddump-splices -dsuppress-un test('T26099', normal, compile_fail, ['']) test('T8306_th', only_ways(['ghci']), ghci_script, ['T8306_th.script']) test('T26862_th', only_ways(['ghci']), ghci_script, ['T26862_th.script']) +test('T27022', normal, compile, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9369b5739826150b0fd067ac8bc1b004... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9369b5739826150b0fd067ac8bc1b004... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Teo Camarasu (@teo)