content: {-# LANGUAGE Unsafe #-}
  {-# LANGUAGE NoImplicitPrelude, MagicHash #-}
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Unsafe.Coerce
  -- Copyright   :  Malcolm Wallace 2006
  -- License     :  BSD-style (see the LICENSE file in the distribution)
  --
  -- Maintainer  :  libraries@haskell.org
  -- Stability   :  experimental
  -- Portability :  portable
  --
  -- The highly unsafe primitive 'unsafeCoerce' converts a value from any
  -- type to any other type.  Needless to say, if you use this function,
  -- it is your responsibility to ensure that the old and new types have
  -- identical internal representations, in order to prevent runtime corruption.
  --
  -- The types for which 'unsafeCoerce' is representation-safe may differ
  -- from compiler to compiler (and version to version).
  --
  --   * Documentation for correct usage in GHC will be found under
  --     'unsafeCoerce#' in GHC.Base (around which 'unsafeCoerce' is just a
  --     trivial wrapper).
  --
  --   * In nhc98, the only representation-safe coercions are between Enum
  --     types with the same range (e.g. Int, Int32, Char, Word32),
  --     or between a newtype and the type that it wraps.
  --
  -----------------------------------------------------------------------------
  
  module Unsafe.Coerce (unsafeCoerce) where
  
  import GHC.Integer () -- for build ordering
  import GHC.Prim (unsafeCoerce#)
  
  local_id :: a -> a
  local_id x = x   -- See Note [Mega-hack for coerce]
  
  {- Note [Mega-hack for coerce]
  
  If we just say
    unsafeCoerce x = unsafeCoerce# x
  then the simple-optimiser that the desugarer runs will eta-reduce to
    unsafeCoerce :: forall (a:*) (b:*). a -> b
    unsafeCoerce = unsafeCoerce#
  And that, sadly, is ill-typed because unsafeCoerce# has OpenKind type variables
  And rightly so, because we shouldn't be calling unsafeCoerce# in a higher
  order way; it has a compulsory unfolding 
     unsafeCoerce# a b x = x |> UnsafeCo a b
  and we really rely on it being inlined pronto. But the simple-optimiser doesn't.
  The identity function local_id delays the eta reduction just long enough
  for unsafeCoerce# to get inlined.
  
  Sigh. This is horrible, but then so is unsafeCoerce.
  -}
  
  unsafeCoerce :: a -> b
  unsafeCoerce x = local_id (unsafeCoerce# x)
    -- See Note [Unsafe coerce magic] in basicTypes/MkId
    -- NB: Do not eta-reduce this definition, else the type checker 
    -- give usafeCoerce the same (dangerous) type as unsafeCoerce#
  