Don't float out lets in between lambdsa
Consider
f = \x. let y = <blah>
in \z. let v = h x y in <stuff>
The full laziness pass will float out that v-binding thus
f = \x. let y = <blah>
v = h x y
in \z. <stuff>
And now (if h is, say, imported) it'll stay like that.
But suppose <blah> simlifies to Just x. Then we allow ourselves to eta-expand thus
f = \x z. let y = <blah>
v = h x y
in <stuff>
Now (an early design choice in the let-floater) we never float the v-binding in between the \x and \z.
This is very non-confluent: a smal change in exactly how rapidly <blah> simplifies can
have a big, irreversible effect on the code for f.
IDEA: extend the let-floater's design choice to not float out between two lambdas, even if they are separated by lets/cases etc. One way to say this is to ask when a lambda gets a new level number compared to its immediately enclosing lambda.
Examples where y gets the same level number as x
\x.\y. blah\x. let binds in \y\x. case scrut of pi -> \y.blah
Examples where y gets the a level number one bigger than x
\x. let v = \y.rhs in blah\x. f (\y.rhs)
This probably won't make a lot of difference, but it'd be worth trying
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |