RuntimeRep-polymorphic unsafeCoerce# can be implemented using lifted-to-lifted unsafeCoerce
Originally discovered in !1869 (closed): !1869 (comment 228164)
We can currently implement unsafeCoerce# (which is more polymorphic, and more unsafe) in terms of unsafeCoerce, as shown by the example in the original comment:
-- An example demonstrating unlifted-to-lifted (and vice versa) using
-- lifted-to-lifted Unsafe.Coerce.unsafeCoerce.
{-# LANGUAGE MagicHash, ScopedTypeVariables, KindSignatures, DataKinds,
PolyKinds #-}
import GHC.Exts
import Unsafe.Coerce
f :: a -> a
f x = x
-- Unlifted-to-lifted
g :: Int# -> Int
g = unsafeCoerce f
-- Lifted-to-unlifted
t :: Int -> Int#
t = unsafeCoerce f
-- Any unlifted to another unlifted
coerce1 :: forall (a :: TYPE 'UnliftedRep) (b :: TYPE 'UnliftedRep) . a -> b
coerce1 = unsafeCoerce f
-- Any unlifted to a lifted
coerce2 :: forall (a :: TYPE 'UnliftedRep) (b :: TYPE 'LiftedRep) . a -> b
coerce2 = unsafeCoerce f
-- Anything to anything else???
coerce_WAT :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) (a :: TYPE r1) (b :: TYPE r2) . a -> b
coerce_WAT = unsafeCoerce f
Uses of this coerce_WAT
type checks:
-- This typechecks
foo :: a
foo = coerce_WAT 1#
Simon says in the original MR:
The fact that you can coax unsafeCoerce to do super-dangrous things is a bit surprising, but it's more of a bug, a curiosity, than a feature.
Hence this issue.