Should exhaustiveness testing be on by default?
Simon Marlow
marlowsd at gmail.com
Sun Jun 7 10:32:54 EDT 2009
Claus Reinke wrote:
> Perhaps I've been misunderstanding what you mean by "lexical stack"?
> "lexical" to me implies only scope information, nothing related to run
> time call chains, which would be "dynamic". In the "dynamic" case, one
> can then distinguish between call-by-need stack (what actually happens
> in GHC) and call-by-value stack (pretend that everything is strict).
Ah, ok. Terminology mismatch. My "lexical call stack" and your
"pseudo-cbv" are almost the same thing, I think.
The way a cost-centre stack is built is described in the docs:
http://www.haskell.org/ghc/docs/latest/html/users_guide/profiling.html#prof-rules
> What the cost-centre stack delivers appears to be more than scopes,
> and less than a full static call graph (which would have to include non
> deterministic branches, since the actual choice of branches depends on
> runtime information) - it seems to use runtime information to give a
> slice of the full call graph (eg, not all call sites that could call the
> current function, but only the one that did so in the current run)?
I'm not sure what you mean here. e.g. "non-deterministic branches"?
Obviously the shape of the call stack depends upon values at runtime.
>>> Here are the +RTS -xc and mapException outputs together (..
>>> - they seem to complement each other (-xc has no locations, but names
>>> for the lexical stack; mapError has no names, but locations for the
>>> dynamic stack; we're still missing the parameters for either stack):
>>
>> I'm not claiming that +RTS -xc in its present form is what you want.
>> I'm interested in finding an underlying mechanism that allows the
>> right information to be obtained; things like source locations and
>> free variables are just decoration.
>
> And I'm saying that adding mapException annotations is a way to get
> there, with very little extra effort (just the get-the-source-location part
> of the finding-the-needle transformation would be sufficient).
mapException exposes information about the call-by-need stack, which is
not what you want (I claim).
>> Now, most of the existing methods have problems with CAFs. I doubt
>> that the problems with CAFs are fixable using the source-to-source
>> transformation methods, but I think they might be fixable using
>> cost-centre stacks.
>
> One of the nice things about my suggestion to mix an "annotate
> with mapException" transformation with cost-centre stacks is that
> it would cover CAFs as well. As another example, I tried the
> nofib-buggy:anna test case discussed at
> http://hackage.haskell.org/trac/ghc/wiki/ExplicitCallStack/StackTraceExperience
>
>
> which does have just such a CAF problem (the error is caused in a local
> CAF, and raised in a standard library CAF), amongst other nasty
> features (no CPP/sed only transformation will handle infix applications,
> the initial error message doesn't even tell us where to start annotating).
The CAF problem I'm referring to is a bit different - the goal is to get
a good stack trace without affecting performance by more than a constant
factor. i.e. CAFs have to be evaluated no more than once, even when
doing stack tracing. This turns out to be quite hard, especially when
using a source-to-source transformation.
The CCS implementation currently errs on the side of not giving you much
information, but without re-evaluating CAFs. Hence you get a
not-very-helpful call stack. However, it wouldn't be difficult to
report the call stack from the site that first evaluated the CAF.
> - the initial error is "<GHC.Err.CAF>Main: divide by zero"
> - this doesn't tell us where the issue is, so we have to annotate all
> calls to 'div', which we do by wrapping in 'mapException',
So yes, you can use mapException to get the dynamic call stack. I'm not
keen on this approach though, because I think the dynamic call stack is
not what you want.
Also, mapExceptionn is not helpful for doing profiling or displaying the
call stack at a breakpoint, and I think a general call-stack mechanism
should enable both of those.
Cheers,
Simon
More information about the Glasgow-haskell-users
mailing list