diff options
author | Ben Gamari <ben@smart-cactus.org> | 2020-06-02 17:09:43 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-06-14 15:35:23 -0400 |
commit | 9a7462fb6b8bdd6326a607bbd7b9453eb588193b (patch) | |
tree | 8300a7c5da0b49c63b81946bf94b3f8c4efc3d59 | |
parent | c0e6dee99242eff08420176a36d77b715972f1f2 (diff) | |
download | haskell-9a7462fb6b8bdd6326a607bbd7b9453eb588193b.tar.gz |
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.
-rw-r--r-- | compiler/GHC/CoreToStg.hs | 5 | ||||
-rw-r--r-- | libraries/base/Unsafe/Coerce.hs | 5 |
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 |