Avoid evaluating unsafe coercions before the safety checks
Only inline unsafeCoerce in CorePrep, to avoid floating unsafeCoerce calls out and evaluating a cast before the check for its safety.
Here's an example of how this happens (from the regression test T16893 -- not included in this patch):
$wcloseComplex d ww
= case sameTypeRep ww t1 of
True -> case ww |> (UnsafeCo ...) of { OpenComplex .. -> ... }
False -> case sameTypeRep ww t2 of
True -> case ww |> (UnsafeCo ...) of { CloseComplex .. -> ... }
False -> ...
The two cases on ww are both evaluating something we know is evaluated so we
float the cases on ww
out:
$wcloseComplex d ww
= case ww |> (UnsafeCo ...) of { OpenComplex .. ->
case ww |> (UnsafeCo ...) of { CloseComplex .. ->
case sameTypeRep ww t1 of
True -> ...
False -> case sameTypeRep ww t2 of
True -> ...
False -> ...
Which is bogus as ww can't be both OpenComplex
and CloseComplex
.
With this patch we avoid floating unsafe coercions by removing the "compulsory
unfolding" of unsafeCoerce#
(making it opaque to the simplifier) and then
eliminating it in CorePrep. (this is similar to how we handle GHC.Magic.lazy
or GHC.Magic.noinline
)
Fixes #16893 (closed)
Edited by Ömer Sinan Ağacan