[GHC] #13370: exprIsBottom inconsistend with strictness analyser
GHC
ghc-devs at haskell.org
Fri Mar 3 11:48:07 UTC 2017
#13370: exprIsBottom inconsistend with strictness analyser
-------------------------------------+-------------------------------------
Reporter: simonpj | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
Because of `Note [IO hack in the demand analyser]` (which I hate), an
expression like
{{{
f :: Int -> State# RealWorld -> (# State# RealWorld, Int #)
f x s = case blah of (# s::State# RealWorld, r::() #) ->
error (show x)
}}}
is not reported as a bottoming function by the strictness analyser.
But `exprBotStrictness_maybe` will say that the RHS ''is'' bottoming.
That ultimately comes from `CoreArity.arityType` which has no analogous
hack to the demand analyser.
These can't both be right! We could
* Cripple `exprBotStrictness_maybe` a bit by adding the hack there too.
* Weaken the hack so that it propagates divergence.
The demand-analyser hack note says
{{{
{- Note [IO hack in the demand analyser]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There's a hack here for I/O operations. Consider
case foo x s of { (# s, r #) -> y }
Is this strict in 'y'? Normally yes, but what if 'foo' is an I/O
operation that simply terminates the program (not in an erroneous way)?
In that case we should not evaluate 'y' before the call to 'foo'.
Hackish solution: spot the IO-like situation and add a virtual branch,
as if we had
case foo x s of
(# s, r #) -> y
other -> return ()
So the 'y' isn't necessarily going to be evaluated
A more complete example (Trac #148, #1592) where this shows up is:
do { let len = <expensive> ;
; when (...) (exitWith ExitSuccess)
; print len }
}}}
I wonder if we could weaken the hack so that it propagated divergence
/exception-thowing, while still making mentioned variables lazy. The big
reason I'd like to do this is if we have
{{{
case f x s of (# s',r #) -> BIG
}}}
then I really want to discard the alternative (since `f x s` is guaranteed
to throw an exception) to give
{{{
case f x s of {}
}}}
This is absolutely kosher; no change in evaluation order or anything.
But weakening the IO hack in this way can change strictness. For example
{{{
g A x y z s = x `seq` y `seq` (# s, () #)
g B x y z s = x `seq` case blah2 of (# s', _ #) ->
y `seq` (# s', () #)
g C x y z s = case blah of (# s', _ #) ->
error (show z)
}}}
Currently we treat this as lazy in x,y and z. With the above change, it'd
become strict in `x` but not `y` or `z`, which is a little weird.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13370>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list