Skip to content

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
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information