A question about the Callback
example (with functions h1
and h2
and useDebbugable
). If, instead of doing putStrLn $ "n = " ++ show n ++ " at " ++ prettyCallStack callStack
in g2
, I do
g2 :: HasCallStack => Int -> IO ()
g2 n = do
throwIO (userError "foo")
Then the exception that bubbles up and is printed doesn’t mention g1
or g2
. Shouldn’t it?
HasCallStack backtrace:
collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
throwIO, called at libraries/exceptions/src/Control/Monad/Catch.hs:371:12 in exceptions-0.10.7-3f06:Control.Monad.Catch
throwM, called at libraries/exceptions/src/Control/Monad/Catch.hs:381:7 in exceptions-0.10.7-3f06:Control.Monad.Catch
generalBracket, called at src/Debug/Provenance/Scope.hs:44:5 in debuggable-0.1.0-ddebb9d545ffc4eda207d06c6f5bb3e3e629385347299f3f1c960b2508033984:Debug.Provenance.Scope
scoped, called at app/Main.hs:27:8 in deb-0.1.0.0-inplace-deb:Main
h2, called at app/Main.hs:24:8 in deb-0.1.0.0-inplace-deb:Main
h1, called at app/Main.hs:30:17 in deb-0.1.0.0-inplace-deb:Main
useDebuggable, called at app/Main.hs:37:5 in deb-0.1.0.0-inplace-deb:Main
Edit: g1
and g2
are also missing in the withoutDebuggable
case, if I throw the exception and don’t use Callback
:
collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
throwIO, called at libraries/exceptions/src/Control/Monad/Catch.hs:371:12 in exceptions-0.10.7-3f06:Control.Monad.Catch
throwM, called at libraries/exceptions/src/Control/Monad/Catch.hs:381:7 in exceptions-0.10.7-3f06:Control.Monad.Catch
generalBracket, called at src/Debug/Provenance/Scope.hs:44:5 in debuggable-0.1.0-ddebb9d545ffc4eda207d06c6f5bb3e3e629385347299f3f1c960b2508033984:Debug.Provenance.Scope
scoped, called at app/Main.hs:13:8 in deb-0.1.0.0-inplace-deb:Main
f2, called at app/Main.hs:10:8 in deb-0.1.0.0-inplace-deb:Main
f1, called at app/Main.hs:33:21 in deb-0.1.0.0-inplace-deb:Main
withoutDebuggable, called at app/Main.hs:38:5 in deb-0.1.0.0-inplace-deb:Main
So it has to do with how exceptions bubble up and interact with HasCallStack
, not with Callback
.
Edit#2: If I remove the use of “scoped”, g1
and g2
start to appear
f2 :: HasCallStack => (Int -> IO ()) -> IO ()
-- f2 k = scoped $ k 1
f2 k = k 1
h2 :: HasCallStack => Callback IO Int () -> IO ()
-- h2 k = scoped $ invokeCallback k 1
h2 k = invokeCallback k 1
HasCallStack backtrace:
collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
throwIO, called at app/Main.hs:22:5 in deb-0.1.0.0-inplace-deb:Main
g2, called at app/Main.hs:17:8 in deb-0.1.0.0-inplace-deb:Main
g1, called at app/Main.hs:35:24 in deb-0.1.0.0-inplace-deb:Main
withoutDebuggable, called at app/Main.hs:40:5 in deb-0.1.0.0-inplace-deb:Main
Thanks for sharing! There are some really interesting features to be unlocked with HasCallStack
. Here’s one that I’ve just written up: Domain errors with HasCallStack
@adamgundry Very cool! Are there any plans to upstream that into base? I’d imagine you’d like to get some feedback from users first?