Teach strictness analysis about `catch`-like operations
Consider the catch#
primop,
catch# :: (State# RealWorld -> (# State# RealWorld, a #) ) -- ^ thing to catch exceptions from
-> (b -> State# RealWorld -> (# State# RealWorld, a #) ) -- ^ exception handler
-> State# RealWorld
-> (# State# RealWorld, a #)
Semantically, this operation will always evaluate its first argument. Ideally we would indicate this in the primop's strictness signature in primops.txt.pp
. Sadly, we can't do this at the moment due to a subtle wrinkle (discovered in #10712 (closed)):
Consider,
let r = \st -> raiseIO# blah st
in catch (\st -> ...(r st)..) handler st
If we give the first argument of catch a strict signature, we'll get
a demand C(S)
for r
; that is, r
is definitely called with one
argument, which indeed it is. The trouble comes when we feed C(S)
into r
's RHS as the demand of the body as this will lead us to conclude that
the whole let
will diverge; clearly this isn't right.
As Simon noted in ticket:10712#comment:103206,
There's something very special about catch: it turns divergence into non-divergence.
In order to apply a proper strictness signature to catch
-like operations we would need to teach the strictness analyzer about this property.
Trac metadata
Trac field | Value |
---|---|
Version | 7.10.3 |
Type | FeatureRequest |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | simonpj |
Operating system | |
Architecture |