summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/GHC/CoreToStg.hs5
-rw-r--r--libraries/base/Unsafe/Coerce.hs5
2 files changed, 9 insertions, 1 deletions
diff --git a/compiler/GHC/CoreToStg.hs b/compiler/GHC/CoreToStg.hs
index 8657b5a84c..42369fe45b 100644
--- a/compiler/GHC/CoreToStg.hs
+++ b/compiler/GHC/CoreToStg.hs
@@ -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
diff --git a/libraries/base/Unsafe/Coerce.hs b/libraries/base/Unsafe/Coerce.hs
index cfb4eac439..aaf2a031ba 100644
--- a/libraries/base/Unsafe/Coerce.hs
+++ b/libraries/base/Unsafe/Coerce.hs
@@ -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