Skip to content

Commit 1f2c545

Browse files
committed
Fix #741: Remove CoerceText, GHC >=7.8 has Coercible
1 parent 80c787d commit 1f2c545

File tree

3 files changed

+20
-32
lines changed

3 files changed

+20
-32
lines changed

Data/Aeson/Types/FromJSON.hs

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -419,38 +419,28 @@ class FromJSONKey a where
419419
default fromJSONKeyList :: FromJSON a => FromJSONKeyFunction [a]
420420
fromJSONKeyList = FromJSONKeyValue parseJSON
421421

422-
-- | With GHC 7.8+ we carry around @'Coercible' 'Text' a@ dictionary,
423-
-- to give us an assurance that the program will not segfault.
424-
-- Unfortunately we cannot enforce that the 'Eq' instances or the
425-
-- 'Hashable' instances for 'Text' and @a@ agree.
426-
--
427-
-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
428-
-- can be inspected, but cannot be constructed.
429-
data CoerceText a where
430-
CoerceText :: Coercible Text a => CoerceText a
431-
432422
-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
433423
-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
434424
-- instance. The other three data constructors for this type all correspond to
435425
-- 'ToJSONKeyText'. Strictly speaking, 'FromJSONKeyTextParser' is more powerful than
436426
-- 'FromJSONKeyText', which is in turn more powerful than 'FromJSONKeyCoerce'.
437427
-- For performance reasons, these exist as three options instead of one.
438-
data FromJSONKeyFunction a
439-
= FromJSONKeyCoerce !(CoerceText a)
440-
-- ^ uses 'coerce' ('unsafeCoerce' in older GHCs)
441-
| FromJSONKeyText !(Text -> a)
428+
data FromJSONKeyFunction a where
429+
FromJSONKeyCoerce :: Coercible Text a => FromJSONKeyFunction a
430+
-- ^ uses 'coerce'
431+
FromJSONKeyText :: !(Text -> a) -> FromJSONKeyFunction a
442432
-- ^ conversion from 'Text' that always succeeds
443-
| FromJSONKeyTextParser !(Text -> Parser a)
433+
FromJSONKeyTextParser :: !(Text -> Parser a) -> FromJSONKeyFunction a
444434
-- ^ conversion from 'Text' that may fail
445-
| FromJSONKeyValue !(Value -> Parser a)
435+
FromJSONKeyValue :: !(Value -> Parser a) -> FromJSONKeyFunction a
446436
-- ^ conversion for non-textual keys
447437

448438
-- | Only law abiding up to interpretation
449439
instance Functor FromJSONKeyFunction where
450-
fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce)
451-
fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
452-
fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
453-
fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
440+
fmap h FromJSONKeyCoerce = FromJSONKeyText (h . coerce)
441+
fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
442+
fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
443+
fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
454444

455445
-- | Construct 'FromJSONKeyFunction' for types coercible from 'Text'. This
456446
-- conversion is still unsafe, as 'Hashable' and 'Eq' instances of @a@ should be
@@ -463,7 +453,7 @@ instance Functor FromJSONKeyFunction where
463453
fromJSONKeyCoerce ::
464454
Coercible Text a =>
465455
FromJSONKeyFunction a
466-
fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
456+
fromJSONKeyCoerce = FromJSONKeyCoerce
467457

468458
-- | Semantically the same as @coerceFromJSONKeyFunction = fmap coerce = coerce@.
469459
--
@@ -473,10 +463,6 @@ coerceFromJSONKeyFunction ::
473463
FromJSONKeyFunction a -> FromJSONKeyFunction b
474464
coerceFromJSONKeyFunction = coerce
475465

476-
{-# RULES
477-
"FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
478-
fmap id x = x
479-
#-}
480466
{-# RULES
481467
"FromJSONKeyCoerce: fmap coerce" forall x .
482468
fmap coerce x = coerceFromJSONKeyFunction x
@@ -1887,7 +1873,7 @@ instance FromJSON a => FromJSON (IntMap.IntMap a) where
18871873

18881874
instance (FromJSONKey k, Ord k) => FromJSON1 (M.Map k) where
18891875
liftParseJSON p _ = case fromJSONKey of
1890-
FromJSONKeyCoerce _ -> withObject "Map" $
1876+
FromJSONKeyCoerce -> withObject "Map" $
18911877
fmap (H.foldrWithKey (M.insert . unsafeCoerce) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)
18921878
FromJSONKeyText f -> withObject "Map" $
18931879
fmap (H.foldrWithKey (M.insert . f) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)
@@ -1967,7 +1953,7 @@ instance (Eq a, Hashable a, FromJSON a) => FromJSON (HashSet.HashSet a) where
19671953

19681954
instance (FromJSONKey k, Eq k, Hashable k) => FromJSON1 (H.HashMap k) where
19691955
liftParseJSON p _ = case fromJSONKey of
1970-
FromJSONKeyCoerce _ -> withObject "HashMap ~Text" $
1956+
FromJSONKeyCoerce -> withObject "HashMap ~Text" $
19711957
uc . H.traverseWithKey (\k v -> p v <?> Key k)
19721958
FromJSONKeyText f -> withObject "HashMap" $
19731959
fmap (mapKey f) . H.traverseWithKey (\k v -> p v <?> Key k)

aeson.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ library
175175
hs-source-dirs: ffi
176176
other-modules: Data.Aeson.Parser.UnescapeFFI
177177

178-
test-suite tests
178+
test-suite aeson-tests
179179
default-language: Haskell2010
180180
type: exitcode-stdio-1.0
181181
hs-source-dirs: tests ffi pure

tests/UnitTests.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,14 @@ fromJSONKeyAssertions =
349349
#endif
350350
]
351351
where
352-
assertIsCoerce _ (FromJSONKeyCoerce _) = pure ()
353-
assertIsCoerce n _ = assertFailure n
352+
assertIsCoerce :: String -> FromJSONKeyFunction a -> Assertion
353+
assertIsCoerce _ FromJSONKeyCoerce = pure ()
354+
assertIsCoerce n _ = assertFailure n
354355

355356
#if __GLASGOW_HASKELL__ >= 710
356-
assertIsCoerce' _ (FromJSONKeyCoerce _) = pure ()
357-
assertIsCoerce' n _ = pickWithRules (assertFailure n) (pure ())
357+
assertIsCoerce' :: String -> FromJSONKeyFunction a -> Assertion
358+
assertIsCoerce' _ FromJSONKeyCoerce = pure ()
359+
assertIsCoerce' n _ = pickWithRules (assertFailure n) (pure ())
358360

359361
-- | Pick the first when RULES are enabled, e.g. optimisations are on
360362
pickWithRules

0 commit comments

Comments
 (0)