Eta-expansion can cause binders in callers to become lazier.
Consider this code:
foo !x = ...
bar =
let x = <thunk>
in foo x
Given that foo
is strict in it's first arg one would hope that bar eventually compiles down to code such as:
bar =
case <thunk> of x
_DEFAULT -> foo x
And that's generally what happens. However if we eta-expand foo
instead we get:
foo !x y = ...
bar =
let x = <thunk>
in \y -> foo x y
This happens since now only once bar
is applied to an additional argument x
will be evaluated.
This can be good or bad depending on the code in question, but it's definitely surprising.
I observed this happening in #22425 (closed)
I think this has a potential bad interaction with when the simplifier drops seqs that I haven't yet seen in the wild.
In particular we might start out with:
-- foo has arity 1
bar x =
case x of x' -> foo x'
-- The simplifier sees that foo is strict in x' and will drop the seq
-- foo has arity 1
bar x =
foo x'
-- We eta expand foo
-- foo has arity 2
bar x =
\y -> foo x' y
And suddenly forcing bar x
no longer forces x
despite the user potentially having explicitly written it to do so.
But as I said I haven't observed the later part in the wild yet and haven't tried to come up with a reproducer. I doubt it happens often in practice.
@sgraf812 You might find this interesting/have more to say about this.