From 566a804839c9d24e758632f3275c10b30467f7c8 Mon Sep 17 00:00:00 2001 From: Utku Demir Date: Fri, 11 Jun 2021 21:14:22 +1200 Subject: [PATCH] Remove a 'unsafeCoerce' from 'Unsafe.coerce' (#330) Previously, the linear `Unsafe.coerce` was implemented using two `unsafeCoerce`'s, one to get a function `a -> b`, and another one to cast that function to be a linear one. After the unsafe equality proofs change[1], we have a `unsafeEqualityProof` function to cast two types to be the same without looking at the value, so we can linearly return it, removing the need for the outer `unsafeCoerce`. This removes one allocation from the generated STG code for 'Data.Array.Unlifted.get', improving the performance slightly. [1]: https://gitlab.haskell.org/ghc/ghc/-/commit/74ad75e87317196c600dfabc61aee1b87d95c214 --- src/Unsafe/Linear.hs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Unsafe/Linear.hs b/src/Unsafe/Linear.hs index 3c2ce267..75eb918c 100644 --- a/src/Unsafe/Linear.hs +++ b/src/Unsafe/Linear.hs @@ -1,5 +1,8 @@ {-# LANGUAGE KindSignatures #-} {-# LANGUAGE RankNTypes #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE LinearTypes #-} @@ -29,8 +32,11 @@ import qualified Unsafe.Coerce as NonLinear import GHC.Exts (TYPE, RuntimeRep) -- | Linearly typed @unsafeCoerce@ -coerce :: a %1-> b -coerce = NonLinear.unsafeCoerce NonLinear.unsafeCoerce +coerce :: forall a b. a %1-> b +coerce a = + case NonLinear.unsafeEqualityProof @a @b of + NonLinear.UnsafeRefl -> a +{-# INLINE coerce #-} -- | Converts an unrestricted function into a linear function toLinear