Teo Camarasu pushed to branch wip/T27022 at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • changelog.d/T27022
    1
    +section: compiler
    
    2
    +synopsis: Fix a divergence in the interaction between ``recover`` and ``putQ`` between the internal and external interpreter
    
    3
    +description: The ``recover`` method in TemplateHaskell now behaves the same 
    
    4
    +  with the internal and external interpreter.
    
    5
    +  In the past, when an error was encountered in a computation in a ``recover`` block,
    
    6
    +  the external interpreter would discard any state changes from ``putQ``,
    
    7
    +  whereas the internal interpreter would not.
    
    8
    +  This was a long-standing error in the implementation of the external interpreter.
    
    9
    +  Both now keep state changes from ``putQ`` in ``recover`` blocks.
    
    10
    +mr: !15994
    
    11
    +issues: #27022

  • libraries/ghci/GHCi/TH.hs
    ... ... @@ -175,9 +175,7 @@ instance TH.Quasi GHCiQ where
    175 175
         e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) sRef
    
    176 176
         remoteTHCall (qsPipe s) (EndRecover (isLeft e))
    
    177 177
         case e of
    
    178
    -      Left GHCiQException{} ->
    
    179
    -        -- in case of error, restore the state to the start of the `recover` block.
    
    180
    -        newIORef s >>= h
    
    178
    +      Left GHCiQException{} -> h sRef
    
    181 179
           Right r -> return r
    
    182 180
       qLookupName isType occ = ghcCmd (LookupName isType occ)
    
    183 181
       qReify name = ghcCmd (Reify name)
    

  • testsuite/tests/th/T27022.hs
    1
    +{-# LANGUAGE TemplateHaskell #-}
    
    2
    +-- | This tests the behaviour of TH's recover method.
    
    3
    +-- It should behave the same in the internal and external interperter.
    
    4
    +-- In the past, they have diverged, and the external interpreter would roll back the state of putQ/getQ whereas the internal interpreter would not.
    
    5
    +module T27022 where
    
    6
    +
    
    7
    +import Language.Haskell.TH.Syntax
    
    8
    +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
    650 650
     test('T26099', normal, compile_fail, [''])
    
    651 651
     test('T8306_th', only_ways(['ghci']), ghci_script, ['T8306_th.script'])
    
    652 652
     test('T26862_th', only_ways(['ghci']), ghci_script, ['T26862_th.script'])
    
    653
    +test('T27022', normal, compile, [''])