OtherCon[] on lambda binders considered harmful.
Before my tag inference patch we used to attach OtherCon[] unfoldings only to lambda binders representing strict constructor fields. Which is what we will return to doing in !8148 (closed)
That is we would generate things like:
data StrictTuple a b = ST !a !b
foo (ST x y) =
...
case x of x' -> rhs
=>
foo =
\tup ->
case tup of
(ST x y) -> $wfoo x y
$wfoo =
\x [Unf=OtherCon]
y [Unf=OtherCon] ->
...
case x of x' -> rhs
But even that could be wrong (depending on compiler details I don't have paged into my head).
With copious amounts of inlining we might get a chain of events like this:
data StrictTuple a b = ST !a !b
foo (ST x y) =
...
case x of x' -> rhs
bar =
...
foo ($WST u v)
-- => WW + inline $WST
foo =
\tup ->
case tup of
(ST x y) -> $wfoo x y
$wfoo =
\x [Unf=OtherCon]
y [Unf=OtherCon] ->
...
case x of x' -> rhs
bar =
...
foo (case u of u' ->
case v of v' ->
ST u' v')
-- =>
-- inline `foo` wrapper
-- remove the redundant case in the worker
$wfoo =
\x [Unf=OtherCon]
y [Unf=OtherCon] ->
...
rhs[x/x']
bar =
...
let con =
case u of u' ->
case v of v' ->
ST u' v'
in
case (con) of
ST x y -> $wfoo x y
-- =>
-- the constructor allocation can cancel out
$wfoo =
\x [Unf=OtherCon]
y [Unf=OtherCon] ->
...
rhs[x/x']
bar =
...
case u of u' ->
case v of v' ->
$wfoo u' v'
We are on thin ice know. If at this point we still consider $wfoo
to be strict in it's first argument the seq on the
first tuple component will disappear completely according to sebastians comment here
and we get something like this which is wrong.
$wfoo =
\x [Unf=OtherCon]
y [Unf=OtherCon] ->
...
rhs[x/x']
bar =
...
case v of v' ->
$wfoo u v'
If we update the demand signature after removing the redundant case x of x'
in the worker then we are save. But I'm unsure if we do!
It seems to depend on all the wrong things happening at all the wrong times so kinda hard to reproduce. But perhaps worth thinking about.