Commit 9a7462fb authored by Ben Gamari's avatar Ben Gamari 🐢 Committed by Marge Bot
Browse files

codeGen: Don't discard live case binders in unsafeEqualityProof logic

Previously CoreToStg would unconditionally discard cases of the form:

    case unsafeEqualityProof of wild { _ -> rhs }

and rather replace the whole thing with `rhs`. However, in some cases
(see #18227) the case binder is still live, resulting in unbound
occurrences in `rhs`. Fix this by only discarding the case if the case
binder is dead.

Fixes #18227.
parent c0e6dee9
......@@ -435,7 +435,10 @@ coreToStgExpr e0@(Case scrut bndr _ alts) = do
let stg = StgCase scrut2 bndr (mkStgAltType bndr alts) alts2
-- See (U2) in Note [Implementing unsafeCoerce] in base:Unsafe.Coerce
case scrut2 of
StgApp id [] | idName id == unsafeEqualityProofName ->
StgApp id [] | idName id == unsafeEqualityProofName
, isDeadBinder bndr ->
-- We can only discard the case if the case-binder is dead
-- It usually is, but see #18227
case alts2 of
[(_, [_co], rhs)] ->
return rhs
......
......@@ -106,6 +106,11 @@ several ways
unsafeEqualityProof to f. As (U5) says, it is implemented as
UnsafeRefl so all is good.
NB: Don't discard the case if the case-binder is used
case unsafeEqualityProof of wild_xx { UnsafeRefl ->
...wild_xx...
That rarely happens, but see #18227.
(U3) In GHC.CoreToStg.Prep.cpeRhsE, if we see
let x = case unsafeEqualityProof ... of
UnsafeRefl -> K e
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment