
#10918: Float once-used let binding into a recursive function
-------------------------------------+-------------------------------------
Reporter: nomeata | Owner:
Type: task | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
-------------------------------------+-------------------------------------
Comment (by nomeata):
One effect, which might or might not be the reason for the paraffin
regression (but certainly obscures the view) is that an inlined expression
seems to float out further than a let-bound expression. More explicitly,
consider this code:
{{{#!hs
foo :: [[Bool]] -> [Bool]
--foo input = [ not y | (x:xs) <- input, y <- (x:xs) ]
foo [] = []
foo (y:ys) =
case y of
[] -> foo ys
(x:xs) ->
let z = foo ys in
let go [] = z
go (y':ys') = not y' : go ys'
in not x : go xs
}}}
With my change, this will be turned into
{{{#!hs
foo :: [[Bool]] -> [Bool]
--foo input = [ not y | (x:xs) <- input, y <- (x:xs) ]
foo [] = []
foo (y:ys) =
case y of
[] -> foo ys
(x:xs) ->
let go [] = foo ys
go (y':ys') = not y' : go ys'
in not x : go xs
}}}
If the compiler would stop here, Iād be happy.
But instead, something interesting happens. In the pristine case, the
binding to `z` is not affected by the level set:
{{{
(let {