[GHC] #12096: Attach stacktrace information to SomeException
GHC
ghc-devs at haskell.org
Tue Mar 28 18:16:47 UTC 2017
#12096: Attach stacktrace information to SomeException
-------------------------------------+-------------------------------------
Reporter: ndtimofeev | Owner: (none)
Type: feature request | Status: new
Priority: normal | Milestone:
Component: Core Libraries | Version: 8.0.1
Resolution: | Keywords: Exceptions
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by ekmett):
Replying to [comment:17 ezyang]:
> Your wiki page does comment that call stacks are preserved if you
rethrow SomeException. But this often doesn't happen in practice. For
example, the `system-fileio` example above rethrows an `IOError`: oops,
call stack lost.
Yes, there is no correct way to preserve this information that doesn't
require the user signalling intent to us. Is what they are throwing a
truly fresh exception or does it derive from one they were given?
On the other hand, the very callstack was information you lacked to begin
with in the old story.
If we extend SomeException you can write code that is compatible with both
the old and new story, and you can make a couple of one line tweaks to
your code to make it so you can preserve the shiny new callstack
information.
If we extend _every_ exception type to carry this information then there
is no code that has ever been written against the exception hierarchy that
can survive the change. Moreover, the Exception class itself then has to
provide a means for us to get in and find and replace the callStack in
these user definable data types, and the user has to construct an empty
callstack to throw their exception in the first place, all of which seems
like a messy, invasive, and slow design.
If we offer some subset of combinators (subject to bikeshedding) like
{{{#!hs
throwWithCallStack :: Exception e => e -> CallStack -> a
withCallStack :: SomeException -> CallStack -> SomeException
rethrow :: SomeException -> a
rethrowAs :: Exception => SomeException -> e -> a
throwIOWithCallStack, rethrowIO, rethrowIOAs ...
catchWithCallStack :: Exception e => IO a -> (e -> CallStack -> IO a) ->
IO a
...
}}}
to the user, then they can fix up these cases as they find them, and in
the meantime they only get the callstack up to the last `throw`, which is
__still__ more information than they have today.
The same scenario involving destroying the source location happens in
languages like c++ w/ throw vs rethrow.
I personally am sad that extending `SomeException` with the callstack
would mean my pretty little prisms into `SomeException` for the various
exception types become a (convenient) lie, but I don't think the
alternative of making the user decorate all of their exception types with
a callstack, mangle every throw so that they include an empty callstack to
kickstart the exception, and supply a callstack update function, and
change all of their existing handlers, most of which do not rethrow, to
deal with an extra argument is a terribly practical alternative.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12096#comment:21>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list