
#11222: Teach strictness analysis about `catch`-like operations -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: feature | Status: new request | Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.10.3 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Runtime Unknown/Multiple | performance bug Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider the `catch#` primop, {{{#!hs 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): Consider, {{{#!hs 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:4,
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. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11222 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler