Stack traces could include one more level of calling functions
Motivation
Here's an example from the GHC user's guide on call stacks:
myHead :: HasCallStack => [a] -> a
myHead [] = error "empty"
myHead (x:xs) = x
bad :: Int
bad = myHead []
CallStack (from HasCallStack):
error, called at Bad.hs:8:15 in main:Bad
myHead, called at Bad.hs:12:7 in main:Bad
Notably, the stack trace does not include the information that myHead
was called inside the function bad
. If bad
had been annotated with HasCallStack
then we would have got that information from the call-stack entry associated with bad
. But arguably we could include this information: if we know the precise calling position of myHead
, then surely we also know the enclosing function!
Of course, since knowing the location lets you find out the enclosing function, a user can work this out. But stack traces are often initially interpreted in isolation, and having an extra function name can provide an extra clue.
(Someone at work has an alternative use case for this; they want to programmatically inspect the stack trace and use the name of the calling function in diagnostic messages from tests. But at the moment they can't get the name of the calling function unless the user also annotates their function with HasCallStack
.)
Proposal
Include the calling function at the point where the stack trace runs out. This could look something like:
CallStack (from HasCallStack):
error, called at Bad.hs:8:15 in main:Bad
myHead, called at Bad.hs:12:7 in main:Bad
bad, called at <unknown>
That is, we "partially" know the next call stack entry. We know the function, but we don't know where it is called.