Skip to content
  • Simon Peyton Jones's avatar
    Comments about stricteness of catch# · e1616343
    Simon Peyton Jones authored
    In "Improve strictness analysis for exceptions"
       commit 7c0fff41
       Author: Simon Peyton Jones <simonpj@microsoft.com>
       Date:   Tue Jul 21 12:28:42 2015 +0100
    
    I made catch# strict in its first argument.  But today I found
    a very old comment suggesting the opposite.  I disagree with the
    old comment, but I've elaborated the Note, which I reproduce here:
    
        {- Note [Strictness for mask/unmask/catch]
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Consider this example, which comes from GHC.IO.Handle.Internals:
           wantReadableHandle3 f ma b st
             = case ... of
                 DEFAULT -> case ma of MVar a -> ...
                 0#      -> maskAsynchExceptions#
                               (\st -> case ma of MVar a -> ...)
        The outer case just decides whether to mask exceptions, but we
        don't want thereby to hide the strictness in 'ma'!  Hence the use
        of strictApply1Dmd.
    
        For catch, we know that the first branch will be evaluated, but
        not necessarily the second.  Hence strictApply1Dmd and
        lazyApply1Dmd
    
        Howver, consider
            catch# (\st -> case x of ...) (..handler..) st
        We'll see that the entire thing is strict in 'x', so 'x' may be
        evaluated before the catch#.  So fi evaluting 'x' causes a
        divide-by-zero exception, it won't be caught.  This seems
        acceptable:
          - x might be evaluated somewhere else outside the catch# anyway
          - It's an imprecise eception anyway.  Synchronous exceptions (in
            the IO monad) will never move in this way.
        There was originally a comment
          "Catch is actually strict in its first argument
           but we don't want to tell the strictness
           analyser about that, so that exceptions stay inside it."
        but tracing it back through the commit logs did not give any
        rationale.  And making catch# lazy has performance costs for
        everyone.
    e1616343