Hannes Siebenhandl pushed to branch wip/fendor/freeze-throw at Glasgow Haskell Compiler / GHC

Commits:

13 changed files:

Changes:

  • libraries/ghc-internal/src/GHC/Internal/Exception.hs
    ... ... @@ -87,7 +87,7 @@ throw e =
    87 87
         -- Note also the absolutely crucial `noinine` in the RHS!
    
    88 88
         --   See Note [Hiding precise exception signature in throw]
    
    89 89
         let se :: SomeException
    
    90
    -        !se = noinline (unsafePerformIO (toExceptionWithBacktrace e))
    
    90
    +        !se = noinline (unsafePerformIO (withFrozenCallStack $ toExceptionWithBacktrace e))
    
    91 91
         in raise# se
    
    92 92
     
    
    93 93
     -- Note [Capturing the backtrace in throw]
    
    ... ... @@ -162,7 +162,12 @@ throw e =
    162 162
     -- primops which allow more precise guidance of the demand analyser's heuristic
    
    163 163
     -- (e.g. #23847).
    
    164 164
     
    
    165
    --- | @since base-4.20.0.0
    
    165
    +-- | Collect a Backtrace and attach it to the 'Exception'.
    
    166
    +--
    
    167
    +-- It is recommended to use 'withFrozenCallStack' when calling this function
    
    168
    +-- in order to avoid leaking implementation details of 'toExceptionWithBacktrace'.
    
    169
    +--
    
    170
    +--  @since base-4.20.0.0
    
    166 171
     toExceptionWithBacktrace :: (HasCallStack, Exception e)
    
    167 172
                              => e -> IO SomeException
    
    168 173
     toExceptionWithBacktrace e
    

  • libraries/ghc-internal/src/GHC/Internal/STM.hs
    ... ... @@ -28,7 +28,7 @@ import GHC.Internal.Base
    28 28
     import GHC.Internal.Exception (Exception, toExceptionWithBacktrace, fromException, addExceptionContext)
    
    29 29
     import GHC.Internal.Exception.Context (ExceptionAnnotation)
    
    30 30
     import GHC.Internal.Exception.Type (WhileHandling(..))
    
    31
    -import GHC.Internal.Stack (HasCallStack)
    
    31
    +import GHC.Internal.Stack (HasCallStack, withFrozenCallStack)
    
    32 32
     
    
    33 33
     -- TVars are shared memory locations which support atomic memory
    
    34 34
     -- transactions.
    
    ... ... @@ -187,7 +187,7 @@ throwSTM e = do
    187 187
         -- N.B. Typically use of unsafeIOToSTM is very much frowned upon as this
    
    188 188
         -- is an easy way to end up with nested transactions. However, we can be
    
    189 189
         -- certain that toExceptionWithBacktrace will not initiate a transaction.
    
    190
    -    se <- unsafeIOToSTM (toExceptionWithBacktrace e)
    
    190
    +    se <- unsafeIOToSTM (withFrozenCallStack $ toExceptionWithBacktrace e)
    
    191 191
         STM $ raiseIO# se
    
    192 192
     
    
    193 193
     -- | Exception handling within STM actions.
    

  • libraries/ghc-internal/tests/backtraces/T15395a.hs
    1
    +import GHC.Internal.Control.Exception
    
    2
    +
    
    3
    +main :: IO ()
    
    4
    +main =
    
    5
    +  throw $ ErrorCall "throw error"

  • libraries/ghc-internal/tests/backtraces/T15395a.stderr
    1
    +T15395a: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
    
    2
    +
    
    3
    +throw error
    
    4
    +
    
    5
    +HasCallStack backtrace:
    
    6
    +  throw, called at T15395a.hs:5:3 in main:Main
    
    7
    +

  • libraries/ghc-internal/tests/backtraces/T15395b.hs
    1
    +import GHC.Internal.Control.Exception
    
    2
    +
    
    3
    +main :: IO ()
    
    4
    +main =
    
    5
    +  throwIO $ ErrorCall "throwIO error"

  • libraries/ghc-internal/tests/backtraces/T15395b.stderr
    1
    +T15395b: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
    
    2
    +
    
    3
    +throwIO error
    
    4
    +
    
    5
    +HasCallStack backtrace:
    
    6
    +  throwIO, called at T15395b.hs:5:3 in main:Main
    
    7
    +

  • libraries/ghc-internal/tests/backtraces/T15395c.hs
    1
    +
    
    2
    +import GHC.Internal.STM
    
    3
    +import GHC.Internal.Control.Exception
    
    4
    +
    
    5
    +main :: IO ()
    
    6
    +main =
    
    7
    +  atomically $ do
    
    8
    +    throwSTM $ ErrorCall "STM error"

  • libraries/ghc-internal/tests/backtraces/T15395c.stderr
    1
    +T15395c: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
    
    2
    +
    
    3
    +STM error
    
    4
    +
    
    5
    +HasCallStack backtrace:
    
    6
    +  throwSTM, called at T15395c.hs:8:5 in main:Main
    
    7
    +

  • libraries/ghc-internal/tests/backtraces/T15395d.hs
    1
    +
    
    2
    +main :: IO ()
    
    3
    +main =
    
    4
    +  undefined

  • libraries/ghc-internal/tests/backtraces/T15395d.stderr
    1
    +T15395d: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
    
    2
    +
    
    3
    +Prelude.undefined
    
    4
    +
    
    5
    +HasCallStack backtrace:
    
    6
    +  undefined, called at T15395d.hs:4:3 in main:Main
    
    7
    +

  • libraries/ghc-internal/tests/backtraces/T15395e.hs
    1
    +
    
    2
    +main :: IO ()
    
    3
    +main =
    
    4
    +  error "error"

  • libraries/ghc-internal/tests/backtraces/T15395e.stderr
    1
    +T15395e: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
    
    2
    +
    
    3
    +error
    
    4
    +
    
    5
    +HasCallStack backtrace:
    
    6
    +  error, called at T15395e.hs:4:3 in main:Main
    
    7
    +

  • libraries/ghc-internal/tests/backtraces/all.T
    1
    +exc_opts = [ when(have_profiling(), extra_ways(['prof']))
    
    2
    +               , when(js_arch(), skip)
    
    3
    +	       , exit_code(1)]
    
    4
    +
    
    1 5
     test('T14532a', [], compile_and_run, [''])
    
    2 6
     test('T14532b', [], compile_and_run, [''])
    
    3
    -test('T26507', [ when(have_profiling(), extra_ways(['prof']))
    
    4
    -               , when(js_arch(), skip)
    
    5
    -	       , exit_code(1)], compile_and_run, [''])
    
    7
    +test('T26507', exc_opts, compile_and_run, [''])
    
    6 8
     
    
    9
    +# Stack traces shouldn't expose implementation details
    
    10
    +test('T15395a', exc_opts, compile_and_run, [''])
    
    11
    +test('T15395b', exc_opts, compile_and_run, [''])
    
    12
    +test('T15395c', exc_opts, compile_and_run, [''])
    
    13
    +test('T15395d', exc_opts, compile_and_run, [''])
    
    14
    +test('T15395e', exc_opts, compile_and_run, [''])