Skip to content
  • Ben Gamari's avatar
    primops: Mark actions evaluated by `catch*` as lazy · 28638dfe
    Ben Gamari authored and Ben Gamari's avatar Ben Gamari committed
    There is something very peculiar about the `catch` family of operations
    with respect to strictness analysis: they turn divergence into
    non-divergence. For this reason, it isn't safe to mark them as strict in
    the expression whose exceptions they are catching. The reason is this:
    
    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.
    
    This is essentially the problem in #10712, which arose when
    7c0fff41 marked the `catch*` primops as
    being strict in the thing to be evaluated. Here I've partially reverted
    this commit, again marking the first argument of these primops as lazy.
    
    Fixes #10712.
    
    Test Plan: Validate checking `exceptionsrun001`
    
    Reviewers: simonpj, austin
    
    Subscribers: thomie
    
    Differential Revision: https://phabricator.haskell.org/D1616
    
    GHC Trac Issues: #10712, #11222
    28638dfe