Skip to content

Commit dfb415f

Browse files
clyringBodigrim
authored andcommitted
Remove support for ghc < 8.4 (#682)
Along the way: * Obseleted CPP and compatibility workarounds were removed * Most remaining CPP conditions are moved into bytestring-cpp-macros.h and given specific feature names * Most imports from ghc-prim are replaced with equivalent imports from base * Data.ByteString.Builder.RealFloat.Internal is left untouched, to avoid unnecessary conflicts # Conflicts: # Data/ByteString/Internal/Type.hs
1 parent 0f89239 commit dfb415f

File tree

10 files changed

+57
-142
lines changed

10 files changed

+57
-142
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@ jobs:
1818
fail-fast: true
1919
matrix:
2020
os: [ubuntu-latest]
21-
ghc: ['8.0', '8.2', '8.4', '8.6', '8.8', '8.10', '9.0', '9.2', '9.4', '9.6', '9.8']
21+
ghc: ['8.4', '8.6', '8.8', '8.10', '9.0', '9.2', '9.4', '9.6', '9.8', '9.10']
2222
include:
2323
- os: macOS-latest
2424
ghc: 'latest'
2525
steps:
2626
- uses: actions/checkout@v4
27-
- name: Install libncurses5 and libtinfo
28-
if: runner.os == 'Linux' && (matrix.ghc == '8.0' || matrix.ghc == '8.2')
29-
run: |
30-
sudo apt-get install libncurses5 libtinfo5
31-
- uses: haskell/actions/setup@v2
27+
- uses: haskell-actions/setup@v2
3228
id: setup-haskell-cabal
3329
with:
3430
ghc-version: ${{ matrix.ghc }}
@@ -67,10 +63,10 @@ jobs:
6763
strategy:
6864
fail-fast: true
6965
matrix:
70-
ghc: ['9.2', '9.4', '9.6']
66+
ghc: ['9.2', '9.4', '9.6', '9.8', '9.10']
7167
steps:
7268
- uses: actions/checkout@v4
73-
- uses: haskell/actions/setup@v2
69+
- uses: haskell-actions/setup@v2
7470
id: setup-haskell-cabal
7571
with:
7672
ghc-version: ${{ matrix.ghc }}
@@ -151,7 +147,7 @@ jobs:
151147
runs-on: ubuntu-latest
152148
steps:
153149
- uses: actions/checkout@v4
154-
- uses: haskell/actions/setup@v2
150+
- uses: haskell-actions/setup@v2
155151
id: setup-haskell-cabal
156152
with:
157153
ghc-version: 'latest'
@@ -172,7 +168,7 @@ jobs:
172168
runs-on: ubuntu-latest
173169
steps:
174170
- uses: actions/checkout@v4
175-
- uses: haskell/actions/setup@v2
171+
- uses: haskell-actions/setup@v2
176172
id: setup-haskell-cabal
177173
with:
178174
ghc-version: 'latest'

Data/ByteString/Internal/Type.hs

Lines changed: 23 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
{-# LANGUAGE UnliftedFFITypes #-}
99
{-# LANGUAGE ViewPatterns #-}
1010

11+
#include "bytestring-cpp-macros.h"
12+
1113
-- |
1214
-- Module : Data.ByteString.Internal.Type
1315
-- Copyright : (c) Don Stewart 2006-2008
@@ -143,10 +145,7 @@ import Data.Maybe (fromMaybe)
143145
import Control.Monad ((<$!>))
144146
#endif
145147

146-
#if !MIN_VERSION_base(4,13,0)
147-
import Data.Semigroup (Semigroup ((<>)))
148-
#endif
149-
import Data.Semigroup (Semigroup (sconcat, stimes))
148+
import Data.Semigroup (Semigroup (..))
150149
import Data.List.NonEmpty (NonEmpty ((:|)))
151150

152151
import Control.DeepSeq (NFData(rnf))
@@ -161,16 +160,13 @@ import Data.Word
161160

162161
import Data.Data (Data(..), mkConstr, mkNoRepType, Constr, DataType, Fixity(Prefix), constrIndex)
163162

164-
import GHC.Base (nullAddr#,realWorld#,unsafeChr)
165-
import GHC.Exts (IsList(..), Addr#, minusAddr#, ByteArray#)
166-
import GHC.CString (unpackCString#)
167-
import GHC.Magic (runRW#, lazy)
163+
import GHC.Base (nullAddr#,realWorld#,unsafeChr,unpackCString#)
164+
import GHC.Exts (IsList(..), Addr#, minusAddr#, ByteArray#, runRW#, lazy)
168165

169-
#define TIMES_INT_2_AVAILABLE MIN_VERSION_ghc_prim(0,7,0)
170-
#if TIMES_INT_2_AVAILABLE
171-
import GHC.Prim (timesInt2#)
166+
#if HS_timesInt2_PRIMOP_AVAILABLE
167+
import GHC.Exts (timesInt2#)
172168
#else
173-
import GHC.Prim ( timesWord2#
169+
import GHC.Exts ( timesWord2#
174170
, or#
175171
, uncheckedShiftRL#
176172
, int2Word#
@@ -181,60 +177,37 @@ import Data.Bits (finiteBitSize)
181177

182178
import GHC.IO (IO(IO))
183179
import GHC.ForeignPtr (ForeignPtr(ForeignPtr)
184-
#if __GLASGOW_HASKELL__ < 900
180+
#if !HS_cstringLength_AND_FinalPtr_AVAILABLE
185181
, newForeignPtr_
186182
#endif
187183
, mallocPlainForeignPtrBytes)
188184

189-
#if MIN_VERSION_base(4,10,0)
190185
import GHC.ForeignPtr (plusForeignPtr)
191-
#else
192-
import GHC.Prim (plusAddr#)
193-
#endif
194186

195-
#if __GLASGOW_HASKELL__ >= 811
196-
import GHC.CString (cstringLength#)
187+
#if HS_cstringLength_AND_FinalPtr_AVAILABLE
188+
import GHC.Exts (cstringLength#)
197189
import GHC.ForeignPtr (ForeignPtrContents(FinalPtr))
198190
#else
199191
import GHC.Ptr (Ptr(..))
200192
#endif
201193

202-
import GHC.Types (Int (..))
194+
import GHC.Int (Int (..))
203195

204-
#if MIN_VERSION_base(4,15,0)
196+
#if HS_unsafeWithForeignPtr_AVAILABLE
205197
import GHC.ForeignPtr (unsafeWithForeignPtr)
206198
#endif
207199

208200
import qualified Language.Haskell.TH.Lib as TH
209201
import qualified Language.Haskell.TH.Syntax as TH
210202

211-
#if !MIN_VERSION_base(4,15,0)
203+
#if !HS_unsafeWithForeignPtr_AVAILABLE
212204
unsafeWithForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
213205
unsafeWithForeignPtr = withForeignPtr
214206
#endif
215207

216208
-- CFILES stuff is Hugs only
217209
{-# CFILES cbits/fpstring.c #-}
218210

219-
#if !MIN_VERSION_base(4,10,0)
220-
-- |Advances the given address by the given offset in bytes.
221-
--
222-
-- The new 'ForeignPtr' shares the finalizer of the original,
223-
-- equivalent from a finalization standpoint to just creating another
224-
-- reference to the original. That is, the finalizer will not be
225-
-- called before the new 'ForeignPtr' is unreachable, nor will it be
226-
-- called an additional time due to this call, and the finalizer will
227-
-- be called with the same address that it would have had this call
228-
-- not happened, *not* the new address.
229-
plusForeignPtr :: ForeignPtr a -> Int -> ForeignPtr b
230-
plusForeignPtr (ForeignPtr addr guts) (I# offset) = ForeignPtr (plusAddr# addr offset) guts
231-
{-# INLINE [0] plusForeignPtr #-}
232-
{-# RULES
233-
"ByteString plusForeignPtr/0" forall fp .
234-
plusForeignPtr fp 0 = fp
235-
#-}
236-
#endif
237-
238211
minusForeignPtr :: ForeignPtr a -> ForeignPtr b -> Int
239212
minusForeignPtr (ForeignPtr addr1 _) (ForeignPtr addr2 _)
240213
= I# (minusAddr# addr1 addr2)
@@ -332,9 +305,7 @@ type StrictByteString = ByteString
332305
pattern PS :: ForeignPtr Word8 -> Int -> Int -> ByteString
333306
pattern PS fp zero len <- BS fp ((0,) -> (zero, len)) where
334307
PS fp o len = BS (plusForeignPtr fp o) len
335-
#if __GLASGOW_HASKELL__ >= 802
336308
{-# COMPLETE PS #-}
337-
#endif
338309

339310
instance Eq ByteString where
340311
(==) = eq
@@ -391,6 +362,7 @@ byteStringDataType = mkNoRepType "Data.ByteString.ByteString"
391362
-- | @since 0.11.2.0
392363
instance TH.Lift ByteString where
393364
#if MIN_VERSION_template_haskell(2,16,0)
365+
-- template-haskell-2.16 first ships with ghc-8.10
394366
lift (BS ptr len) = [| unsafePackLenLiteral |]
395367
`TH.appE` TH.litE (TH.integerL (fromIntegral len))
396368
`TH.appE` TH.litE (TH.BytesPrimL $ TH.Bytes ptr 0 (fromIntegral len))
@@ -401,8 +373,10 @@ instance TH.Lift ByteString where
401373
#endif
402374

403375
#if MIN_VERSION_template_haskell(2,17,0)
376+
-- template-haskell-2.17 first ships with ghc-9.0
404377
liftTyped = TH.unsafeCodeCoerce . TH.lift
405378
#elif MIN_VERSION_template_haskell(2,16,0)
379+
-- template-haskell-2.16 first ships with ghc-8.10
406380
liftTyped = TH.unsafeTExpCoerce . TH.lift
407381
#endif
408382

@@ -478,7 +452,7 @@ unsafePackLenChars len cs0 =
478452
--
479453
unsafePackAddress :: Addr# -> IO ByteString
480454
unsafePackAddress addr# = do
481-
#if __GLASGOW_HASKELL__ >= 811
455+
#if HS_cstringLength_AND_FinalPtr_AVAILABLE
482456
unsafePackLenAddress (I# (cstringLength# addr#)) addr#
483457
#else
484458
l <- c_strlen (Ptr addr#)
@@ -494,7 +468,7 @@ unsafePackAddress addr# = do
494468
-- @since 0.11.2.0
495469
unsafePackLenAddress :: Int -> Addr# -> IO ByteString
496470
unsafePackLenAddress len addr# = do
497-
#if __GLASGOW_HASKELL__ >= 811
471+
#if HS_cstringLength_AND_FinalPtr_AVAILABLE
498472
return (BS (ForeignPtr addr# FinalPtr) len)
499473
#else
500474
p <- newForeignPtr_ (Ptr addr#)
@@ -511,7 +485,7 @@ unsafePackLenAddress len addr# = do
511485
-- @since 0.11.1.0
512486
unsafePackLiteral :: Addr# -> ByteString
513487
unsafePackLiteral addr# =
514-
#if __GLASGOW_HASKELL__ >= 811
488+
#if HS_cstringLength_AND_FinalPtr_AVAILABLE
515489
unsafePackLenLiteral (I# (cstringLength# addr#)) addr#
516490
#else
517491
let len = accursedUnutterablePerformIO (c_strlen (Ptr addr#))
@@ -528,7 +502,7 @@ unsafePackLiteral addr# =
528502
-- @since 0.11.2.0
529503
unsafePackLenLiteral :: Int -> Addr# -> ByteString
530504
unsafePackLenLiteral len addr# =
531-
#if __GLASGOW_HASKELL__ >= 811
505+
#if HS_cstringLength_AND_FinalPtr_AVAILABLE
532506
BS (ForeignPtr addr# FinalPtr) len
533507
#else
534508
-- newForeignPtr_ allocates a MutVar# internally. If that MutVar#
@@ -621,7 +595,7 @@ unpackAppendCharsStrict (BS fp len) xs =
621595

622596
-- | The 0 pointer. Used to indicate the empty Bytestring.
623597
nullForeignPtr :: ForeignPtr Word8
624-
#if __GLASGOW_HASKELL__ >= 811
598+
#if HS_cstringLength_AND_FinalPtr_AVAILABLE
625599
nullForeignPtr = ForeignPtr nullAddr# FinalPtr
626600
#else
627601
nullForeignPtr = ForeignPtr nullAddr# (error "nullForeignPtr")
@@ -1039,7 +1013,7 @@ checkedAdd fun x y
10391013
checkedMultiply :: String -> Int -> Int -> Int
10401014
{-# INLINE checkedMultiply #-}
10411015
checkedMultiply fun !x@(I# x#) !y@(I# y#) = assert (min x y >= 0) $
1042-
#if TIMES_INT_2_AVAILABLE
1016+
#if HS_timesInt2_PRIMOP_AVAILABLE
10431017
case timesInt2# x# y# of
10441018
(# 0#, _, result #) -> I# result
10451019
_ -> overflowError fun

Data/ByteString/Lazy/Internal.hs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,7 @@ import qualified Data.ByteString.Internal.Type as S
5353
import Data.Word (Word8)
5454
import Foreign.Storable (Storable(sizeOf))
5555

56-
#if MIN_VERSION_base(4,13,0)
57-
import Data.Semigroup (Semigroup (sconcat, stimes))
58-
#else
59-
import Data.Semigroup (Semigroup ((<>), sconcat, stimes))
60-
#endif
56+
import Data.Semigroup (Semigroup (..))
6157
import Data.List.NonEmpty (NonEmpty ((:|)))
6258
import Control.DeepSeq (NFData, rnf)
6359

Data/ByteString/Short/Internal.hs

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
88
{-# LANGUAGE TypeFamilies #-}
99
{-# LANGUAGE UnliftedFFITypes #-}
10-
{-# LANGUAGE ViewPatterns #-}
1110

1211
#include "bytestring-cpp-macros.h"
1312

@@ -184,12 +183,6 @@ import Foreign.C.String
184183
( CString
185184
, CStringLen
186185
)
187-
#if !HS_compareByteArrays_PRIMOP_AVAILABLE && !PURE_HASKELL
188-
import Foreign.C.Types
189-
( CSize(..)
190-
, CInt(..)
191-
)
192-
#endif
193186
import Foreign.Marshal.Alloc
194187
( allocaBytes )
195188
import Foreign.Storable
@@ -202,13 +195,9 @@ import GHC.Exts
202195
, byteArrayContents#
203196
, unsafeCoerce#
204197
, copyMutableByteArray#
205-
#if HS_isByteArrayPinned_PRIMOP_AVAILABLE
206198
, isByteArrayPinned#
207199
, isTrue#
208-
#endif
209-
#if HS_compareByteArrays_PRIMOP_AVAILABLE
210200
, compareByteArrays#
211-
#endif
212201
, sizeofByteArray#
213202
, indexWord8Array#, indexCharArray#
214203
, writeWord8Array#
@@ -277,11 +266,7 @@ newtype ShortByteString =
277266
-- but now it is a bundled pattern synonym, provided as a compatibility shim.
278267
pattern SBS :: ByteArray# -> ShortByteString
279268
pattern SBS x = ShortByteString (ByteArray x)
280-
#if __GLASGOW_HASKELL__ >= 802
281269
{-# COMPLETE SBS #-}
282-
-- To avoid spurious warnings from CI with ghc-8.0, we internally
283-
-- use view patterns like (unSBS -> ba#) instead of using (SBS ba#)
284-
#endif
285270

286271
-- | Lexicographic order.
287272
instance Ord ShortByteString where
@@ -331,7 +316,7 @@ empty = create 0 (\_ -> return ())
331316

332317
-- | /O(1)/ The length of a 'ShortByteString'.
333318
length :: ShortByteString -> Int
334-
length (unSBS -> barr#) = I# (sizeofByteArray# barr#)
319+
length (SBS barr#) = I# (sizeofByteArray# barr#)
335320

336321
-- | /O(1)/ Test whether a 'ShortByteString' is empty.
337322
null :: ShortByteString -> Bool
@@ -380,9 +365,6 @@ indexError sbs i =
380365
asBA :: ShortByteString -> ByteArray
381366
asBA (ShortByteString ba) = ba
382367

383-
unSBS :: ShortByteString -> ByteArray#
384-
unSBS (ShortByteString (ByteArray ba#)) = ba#
385-
386368
create :: Int -> (forall s. MutableByteArray s -> ST s ()) -> ShortByteString
387369
create len fill =
388370
assert (len >= 0) $ runST $ do
@@ -449,11 +431,7 @@ createAndTrim2 maxLen1 maxLen2 fill =
449431
{-# INLINE createAndTrim2 #-}
450432

451433
isPinned :: ByteArray# -> Bool
452-
#if HS_isByteArrayPinned_PRIMOP_AVAILABLE
453434
isPinned ba# = isTrue# (isByteArrayPinned# ba#)
454-
#else
455-
isPinned _ = False
456-
#endif
457435

458436
------------------------------------------------------------------------
459437
-- Conversion to and from ByteString
@@ -475,7 +453,7 @@ toShortIO (BS fptr len) = do
475453
-- | /O(n)/. Convert a 'ShortByteString' into a 'ByteString'.
476454
--
477455
fromShort :: ShortByteString -> ByteString
478-
fromShort sbs@(unSBS -> b#)
456+
fromShort sbs@(SBS b#)
479457
| isPinned b# = BS inPlaceFp len
480458
| otherwise = BS.unsafeCreateFp len $ \fp ->
481459
BS.unsafeWithForeignPtr fp $ \p -> copyToPtr sbs 0 p len
@@ -1492,7 +1470,7 @@ partition k = \sbs -> let len = length sbs
14921470
--
14931471
-- @since 0.11.3.0
14941472
elemIndex :: Word8 -> ShortByteString -> Maybe Int
1495-
elemIndex c = \sbs@(unSBS -> ba#) -> do
1473+
elemIndex c = \sbs@(SBS ba#) -> do
14961474
let l = length sbs
14971475
accursedUnutterablePerformIO $ do
14981476
!s <- c_elem_index ba# c (fromIntegral l)
@@ -1510,7 +1488,7 @@ elemIndices k = findIndices (==k)
15101488
--
15111489
-- @since 0.11.3.0
15121490
count :: Word8 -> ShortByteString -> Int
1513-
count w = \sbs@(unSBS -> ba#) -> accursedUnutterablePerformIO $
1491+
count w = \sbs@(SBS ba#) -> accursedUnutterablePerformIO $
15141492
fromIntegral <$> BS.c_count_ba ba# (fromIntegral $ length sbs) w
15151493

15161494
-- | /O(n)/ The 'findIndex' function takes a predicate and a 'ShortByteString' and
@@ -1641,24 +1619,8 @@ compareByteArraysOff :: ByteArray -- ^ array 1
16411619
-> Int -- ^ offset for array 2
16421620
-> Int -- ^ length to compare
16431621
-> Int -- ^ like memcmp
1644-
#if HS_compareByteArrays_PRIMOP_AVAILABLE
16451622
compareByteArraysOff (ByteArray ba1#) (I# ba1off#) (ByteArray ba2#) (I# ba2off#) (I# len#) =
16461623
I# (compareByteArrays# ba1# ba1off# ba2# ba2off# len#)
1647-
#else
1648-
compareByteArraysOff (ByteArray ba1#) ba1off (ByteArray ba2#) ba2off len =
1649-
assert (ba1off + len <= (I# (sizeofByteArray# ba1#)))
1650-
$ assert (ba2off + len <= (I# (sizeofByteArray# ba2#)))
1651-
$ fromIntegral $ accursedUnutterablePerformIO $
1652-
c_memcmp_ByteArray ba1#
1653-
ba1off
1654-
ba2#
1655-
ba2off
1656-
(fromIntegral len)
1657-
1658-
1659-
foreign import ccall unsafe "static sbs_memcmp_off"
1660-
c_memcmp_ByteArray :: ByteArray# -> Int -> ByteArray# -> Int -> CSize -> IO CInt
1661-
#endif
16621624

16631625
------------------------------------------------------------------------
16641626
-- Primop replacements
@@ -1738,7 +1700,7 @@ useAsCStringLen sbs action =
17381700
--
17391701
-- @since 0.11.3.0
17401702
isValidUtf8 :: ShortByteString -> Bool
1741-
isValidUtf8 sbs@(unSBS -> ba#) = accursedUnutterablePerformIO $ do
1703+
isValidUtf8 sbs@(SBS ba#) = accursedUnutterablePerformIO $ do
17421704
let n = length sbs
17431705
-- Use a safe FFI call for large inputs to avoid GC synchronization pauses
17441706
-- in multithreaded contexts.

0 commit comments

Comments
 (0)