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 |