Skip to content

Avoid evaluating unsafe coercions before the safety checks

Ömer Sinan Ağacan requested to merge osa1/ghc:fix_T16893 into master

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

Merge request reports