{-# LANGUAGE CPP #-}

#if __GLASGOW_HASKELL__ >= 708
#define USE_COERCE
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
#else
{-# LANGUAGE Unsafe #-}
#endif
-----------------------------------------------------------------------------
-- |
-- Copyright   :  (C) 2016 Edward Kmett and Eric Mertens
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
-- Stability   :  experimental
-- Portability :  non-portable
--
-- This module provides a shim around 'coerce' that defaults to 'unsafeCoerce'
-- on GHC < 7.8. It also exposes a type-restricted version of '(#.)' that
-- works around a bizarre GHC 7.10–specific bug.
-----------------------------------------------------------------------------
module Control.Lens.Internal.Coerce
  ( coerce
  , coerce'
  , (#..)
  ) where

import Data.Profunctor.Unsafe

#ifdef USE_COERCE

import Data.Coerce

coerce' :: forall a b. Coercible a b => b -> a
coerce' = coerce (id :: a -> a)
{-# INLINE coerce' #-}

(#..) :: (Profunctor p, Coercible c b) => (b -> c) -> p a b -> p a c
(#..) = (#.)
{-# INLINE (#..) #-}

#else

import Unsafe.Coerce

coerce, coerce' :: a -> b
coerce  = unsafeCoerce
coerce' = unsafeCoerce
{-# INLINE coerce #-}
{-# INLINE coerce' #-}

(#..) :: Profunctor p => (b -> c) -> p a b -> p a c
(#..) = (#.)
{-# INLINE (#..) #-}
#endif