DmdAnal: Recognise precise exceptions from case alternatives (#18086)
Consider
m :: IO ()
m = do
putStrLn "foo"
error "bar"
m
(from #18086 (closed)) 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 (closed).