Skip to content
  • Sebastian Graf's avatar
    DmdAnal: Recognise precise exceptions from case alternatives (#18086) · 08dab5f7
    Sebastian Graf authored and Marge Bot's avatar Marge Bot committed
    Consider
    
    ```hs
    m :: IO ()
    m = do
      putStrLn "foo"
      error "bar"
    ```
    
    `m` (from #18086) always throws a (precise or imprecise) exception or
    diverges. Yet demand analysis infers `<L,A>` as demand signature instead
    of `<L,A>x` for it.
    
    That's because the demand analyser sees `putStrLn` occuring in a case
    scrutinee and decides that it has to `deferAfterPreciseException`,
    because `putStrLn` throws a precise exception on some control flow
    paths. This will mask the `botDiv` `Divergence`of the single case alt
    containing `error` to `topDiv`. Since `putStrLn` has `topDiv` itself,
    the final `Divergence` is `topDiv`.
    
    This is easily fixed: `deferAfterPreciseException` works by `lub`ing
    with the demand type of a virtual case branch denoting the precise
    exceptional control flow. We used `nopDmdType` before, but we can be
    more precise and use `exnDmdType`, which is `nopDmdType` with `exnDiv`.
    
    Now the `Divergence` from the case alt will degrade `botDiv` to `exnDiv`
    instead of `topDiv`, which combines with the result from the scrutinee
    to `exnDiv`, and all is well.
    
    Fixes #18086.
    08dab5f7