[commit: packages/containers] changelog-foldtree, cleaned_bugfix394, develop-0.6, develop-0.6-questionable, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-184-generic, revert-408-bugfix_394: Remove unsafeCoerce, use only coerce on GHC 7.8 and later. (b38f240)

git at git.haskell.org git at git.haskell.org
Mon Apr 17 21:36:05 UTC 2017


Repository : ssh://git@git.haskell.org/containers

On branches: changelog-foldtree,cleaned_bugfix394,develop-0.6,develop-0.6-questionable,master,merge-doc-target,merge-fixes-5.9,merge-restrict-fix-5.8,revert-184-generic,revert-408-bugfix_394
Link       : http://git.haskell.org/packages/containers.git/commitdiff/b38f240ab4bec53c5f5800cc1b621a00b4604b2d

>---------------------------------------------------------------

commit b38f240ab4bec53c5f5800cc1b621a00b4604b2d
Author: Milan Straka <fox at ucw.cz>
Date:   Mon Dec 15 09:02:37 2014 +0100

    Remove unsafeCoerce, use only coerce on GHC 7.8 and later.
    
    Also, move the conditional compilation to a local where definition.
    
    On my GHC 7.6.3, there is no heap allocation in the cmm in fromFunction
    for the (Elem . f) closure, so there is no penalty of not using `coerce`.
    Nevertheless, GHC 7.8.3 and GHC-head (15 Dec 2014) do heap-allocate
    trivial closure for (Elem . f), so `coerce` helps.
    
    Back to GHC 7.6.3, I found that the following does not allocate in
    GHC 7.6.3:
      newtype Elem a = Elem a
      elemMap :: Int -> (Int -> b) -> [Elem b]
      elemMap s f = go (Elem . f) 0
       where go :: (Int -> b) -> Int -> [b]
             go f i | i >= s = []
                    | otherwise = f i : go f (i+1)
    Nevertheless, the following does heap-allocate trivial closure for f:
      newtype Elem a = Elem a
      elemMap :: [Int] -> (Int -> b) -> [Elem b]
      elemMap xs f = go (Elem . f) xs
       where go :: (Int -> b) -> [Int] -> [b]
             go f [] = []
             go f (x:xs) = f x : go f xs
    I am not sure what the difference is, but the current fromFunction
    does not allocate too (on 7.6.3).


>---------------------------------------------------------------

b38f240ab4bec53c5f5800cc1b621a00b4604b2d
 Data/Sequence.hs | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/Data/Sequence.hs b/Data/Sequence.hs
index fa80b3f..4c281fc 100644
--- a/Data/Sequence.hs
+++ b/Data/Sequence.hs
@@ -181,14 +181,7 @@ import Data.Data
 #if __GLASGOW_HASKELL__ >= 708
 import Data.Coerce
 import qualified GHC.Exts
-#define COERCE coerce
 #else
-#ifdef __GLASGOW_HASKELL__
-import qualified Unsafe.Coerce
--- Note that by compiling this file with GHC 7.8 or later, we prove that
--- it is safe to use COERCE with earlier GHC versions.
-#define COERCE Unsafe.Coerce.unsafeCoerce
-#endif
 #endif
 #if MIN_VERSION_base(4,8,0)
 import Data.Functor.Identity (Identity(..))
@@ -1365,11 +1358,7 @@ mapWithIndex f' (Seq xs') = Seq $ mapWithIndexTree (\s (Elem a) -> Elem (f' s a)
 fromFunction :: Int -> (Int -> a) -> Seq a
 fromFunction len f | len < 0 = error "Data.Sequence.fromFunction called with negative len"
                    | len == 0 = empty
-#ifdef __GLASGOW_HASKELL__
-                   | otherwise = Seq $ create (COERCE f) 1 0 len
-#else
-                   | otherwise = Seq $ create (Elem . f) 1 0 len
-#endif
+                   | otherwise = Seq $ create (lift_elem f) 1 0 len
   where
     create :: (Int -> a) -> Int -> Int -> Int -> FingerTree a
     create b{-tree_builder-} s{-tree_size-} i{-start_index-} trees = i `seq` s `seq` case trees of
@@ -1397,6 +1386,14 @@ fromFunction len f | len < 0 = error "Data.Sequence.fromFunction called with neg
         mb j = Node3 (3*s) (b j) (b (j + s)) (b (j + 2*s))
         {-# INLINE mb #-}
 
+    lift_elem :: (Int -> a) -> (Int -> Elem a)
+#if __GLASGOW_HASKELL__ >= 708
+    lift_elem g = coerce g
+#else
+    lift_elem g = Elem . g
+#endif
+    {-# INLINE lift_elem #-}
+
 -- Splitting
 
 -- | /O(log(min(i,n-i)))/. The first @i@ elements of a sequence.



More information about the ghc-commits mailing list