diff --git a/Data/Aeson.hs b/Data/Aeson.hs
--- a/Data/Aeson.hs
+++ b/Data/Aeson.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson
 -- Copyright:   (c) 2011-2016 Bryan O'Sullivan
@@ -130,7 +131,6 @@
     , json'
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.Types.FromJSON (ifromJSON)
diff --git a/Data/Aeson/Encode.hs b/Data/Aeson/Encode.hs
--- a/Data/Aeson/Encode.hs
+++ b/Data/Aeson/Encode.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson.Encode
 -- Copyright:   (c) 2012-2016 Bryan O'Sullivan
@@ -8,13 +9,13 @@
 -- Portability: portable
 --
 -- This module is left to supply limited backwards-compatibility.
+
 module Data.Aeson.Encode {-# DEPRECATED "Use Data.Aeson or Data.Aeson.Text instead" #-}
     (
       encode
     , encodeToTextBuilder
     ) where
 
-import Prelude ()
 
 import Data.ByteString.Lazy (ByteString)
 import Data.Text.Lazy.Builder (Builder)
diff --git a/Data/Aeson/Encoding.hs b/Data/Aeson/Encoding.hs
--- a/Data/Aeson/Encoding.hs
+++ b/Data/Aeson/Encoding.hs
@@ -1,8 +1,10 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 --
 -- Functions in this module return well-formed 'Encoding''.
 -- Polymorphic variants, which return @'Encoding' a@, return a textual JSON
 -- value, so it can be used as both @'Encoding'' 'Text'@ and @'Encoding' = 'Encoding'' 'Value'@.
+
 module Data.Aeson.Encoding
     (
     -- * Encoding
@@ -49,6 +51,5 @@
     , value
     ) where
 
-import Prelude ()
 
 import Data.Aeson.Encoding.Internal
diff --git a/Data/Aeson/Encoding/Builder.hs b/Data/Aeson/Encoding/Builder.hs
--- a/Data/Aeson/Encoding/Builder.hs
+++ b/Data/Aeson/Encoding/Builder.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE BangPatterns #-}
-
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TupleSections #-}
 -- |
 -- Module:      Data.Aeson.Encoding.Builder
 -- Copyright:   (c) 2011 MailRank, Inc.
@@ -35,7 +36,6 @@
     , ascii5
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.Internal.Time
@@ -201,7 +201,7 @@
     !(T mh ml)  = twoDigits m
     !(T sh sl)  = twoDigits (fromIntegral real)
     (real,frac) = s `quotRem` pico
-    showFrac = (\x -> ('.', x)) >$< (BP.liftFixedToBounded BP.char7 >*< trunc12)
+    showFrac = ('.',) >$< (BP.liftFixedToBounded BP.char7 >*< trunc12)
     trunc12 = (`quotRem` micro) >$<
               BP.condB (\(_,y) -> y == 0) (fst >$< trunc6) (digits6 >*< trunc6)
     digits6 = ((`quotRem` milli) . fromIntegral) >$< (digits3 >*< digits3)
diff --git a/Data/Aeson/Encoding/Internal.hs b/Data/Aeson/Encoding/Internal.hs
--- a/Data/Aeson/Encoding/Internal.hs
+++ b/Data/Aeson/Encoding/Internal.hs
@@ -1,7 +1,9 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes #-}
+
 module Data.Aeson.Encoding.Internal
     (
     -- * Encoding
@@ -55,7 +57,6 @@
     , comma, colon, openBracket, closeBracket, openCurly, closeCurly
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.Types.Internal (Value)
diff --git a/Data/Aeson/Internal.hs b/Data/Aeson/Internal.hs
--- a/Data/Aeson/Internal.hs
+++ b/Data/Aeson/Internal.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson.Internal
 -- Copyright:   (c) 2015-2016 Bryan O'Sullivan
@@ -22,7 +23,6 @@
     , iparse
     ) where
 
-import Prelude ()
 
 import Data.Aeson.Types.Internal
 import Data.Aeson.Types.FromJSON (ifromJSON)
diff --git a/Data/Aeson/Internal/Functions.hs b/Data/Aeson/Internal/Functions.hs
--- a/Data/Aeson/Internal/Functions.hs
+++ b/Data/Aeson/Internal/Functions.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson.Functions
 -- Copyright:   (c) 2011-2016 Bryan O'Sullivan
@@ -14,7 +15,6 @@
     , mapKey
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Hashable (Hashable)
diff --git a/Data/Aeson/Parser.hs b/Data/Aeson/Parser.hs
--- a/Data/Aeson/Parser.hs
+++ b/Data/Aeson/Parser.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson.Parser
 -- Copyright:   (c) 2012-2016 Bryan O'Sullivan
@@ -45,7 +46,6 @@
     , eitherDecodeStrictWith
     ) where
 
-import Prelude ()
 
 import Data.Aeson.Parser.Internal (decodeStrictWith, decodeWith, eitherDecodeStrictWith, eitherDecodeWith, json, json', jstring, scientific, value, value')
 
diff --git a/Data/Aeson/Parser/Internal.hs b/Data/Aeson/Parser/Internal.hs
--- a/Data/Aeson/Parser/Internal.hs
+++ b/Data/Aeson/Parser/Internal.hs
@@ -1,10 +1,10 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 #if MIN_VERSION_ghc_prim(0,3,1)
 {-# LANGUAGE MagicHash #-}
 #endif
-
 -- |
 -- Module:      Data.Aeson.Parser.Internal
 -- Copyright:   (c) 2011-2016 Bryan O'Sullivan
@@ -35,7 +35,6 @@
     , eitherDecodeStrictWith
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative ((<|>))
diff --git a/Data/Aeson/Parser/Time.hs b/Data/Aeson/Parser/Time.hs
--- a/Data/Aeson/Parser/Time.hs
+++ b/Data/Aeson/Parser/Time.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Data.Aeson.Parser.Time
     (
       run
@@ -9,7 +11,6 @@
     , zonedTime
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Attoparsec.Text (Parser)
diff --git a/Data/Aeson/TH.hs b/Data/Aeson/TH.hs
--- a/Data/Aeson/TH.hs
+++ b/Data/Aeson/TH.hs
@@ -116,7 +116,6 @@
     , mkLiftParseJSON2
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative ((<|>))
diff --git a/Data/Aeson/Text.hs b/Data/Aeson/Text.hs
--- a/Data/Aeson/Text.hs
+++ b/Data/Aeson/Text.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 -- |
 -- Module:      Data.Aeson.Text
@@ -14,13 +15,13 @@
 --
 -- You can use the conversions to 'Builder's when embedding JSON messages as
 -- parts of a protocol.
+
 module Data.Aeson.Text
     (
       encodeToLazyText
     , encodeToTextBuilder
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.Types (Value(..), ToJSON(..))
diff --git a/Data/Aeson/Types.hs b/Data/Aeson/Types.hs
--- a/Data/Aeson/Types.hs
+++ b/Data/Aeson/Types.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson.Types
 -- Copyright:   (c) 2011-2016 Bryan O'Sullivan
@@ -124,7 +125,6 @@
     , defaultTaggedObject
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.Encoding (Encoding, unsafeToEncoding, fromEncoding, Series, pairs)
diff --git a/Data/Aeson/Types/Class.hs b/Data/Aeson/Types/Class.hs
--- a/Data/Aeson/Types/Class.hs
+++ b/Data/Aeson/Types/Class.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 
@@ -91,7 +92,6 @@
     , (.!=)
     ) where
 
-import Prelude ()
 
 import Data.Aeson.Types.FromJSON
 import Data.Aeson.Types.Generic (One, Zero)
diff --git a/Data/Aeson/Types/FromJSON.hs b/Data/Aeson/Types/FromJSON.hs
--- a/Data/Aeson/Types/FromJSON.hs
+++ b/Data/Aeson/Types/FromJSON.hs
@@ -6,6 +6,7 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -76,7 +77,6 @@
     , parseOptionalFieldWith
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative ((<|>), Const(..))
@@ -107,6 +107,7 @@
 import Data.Traversable as Tr (sequence)
 import Data.Vector (Vector)
 import Data.Version (Version, parseVersion)
+import Data.Void (Void)
 import Data.Word (Word16, Word32, Word64, Word8)
 import Foreign.Storable (Storable)
 import Foreign.C.Types (CTime (..))
@@ -139,6 +140,16 @@
 import qualified Data.Vector.Storable as VS
 import qualified Data.Vector.Unboxed as VU
 
+import qualified GHC.Exts as Exts
+import qualified Data.Primitive.Array as PM
+import qualified Data.Primitive.SmallArray as PM
+import qualified Data.Primitive.Types as PM
+
+#if MIN_VERSION_primitive(0,6,4)
+import qualified Data.Primitive.UnliftedArray as PM
+import qualified Data.Primitive.PrimArray as PM
+#endif
+
 #ifndef HAS_COERCIBLE
 #define HAS_COERCIBLE (__GLASGOW_HASKELL__ >= 707)
 #endif
@@ -657,7 +668,7 @@
 -- when @value@ is a 'Number' and fails using @'typeMismatch' expected@
 -- otherwise.
 --
--- The conversion will also fail wyth a @'typeMismatch' if the
+-- The conversion will also fail with a @'typeMismatch' if the
 -- 'Scientific' exponent is larger than 1024.
 withBoundedScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a
 withBoundedScientific _ f v@(Number scientific) =
@@ -786,6 +797,11 @@
 -- Generic parseJSON
 -------------------------------------------------------------------------------
 
+instance GFromJSON arity V1 where
+    -- Whereof we cannot format, thereof we cannot parse:
+    gParseJSON _ _ _ = fail "Attempted to parse empty type"
+
+
 instance OVERLAPPABLE_ (GFromJSON arity a) => GFromJSON arity (M1 i c a) where
     -- Meta-information, which is not handled elsewhere, is just added to the
     -- parsed value:
@@ -1198,7 +1214,9 @@
     parseJSON = parseJSON2
     {-# INLINE parseJSON #-}
 
-
+instance FromJSON Void where
+    parseJSON _ = fail "Cannot parse Void"
+    {-# INLINE parseJSON #-}
 
 instance FromJSON Bool where
     parseJSON = withBool "Bool" pure
@@ -1672,6 +1690,28 @@
              Just d -> pure (DotNetTime d)
              _      -> fail "could not parse .NET time"
     {-# INLINE parseJSON #-}
+
+-------------------------------------------------------------------------------
+-- primitive
+-------------------------------------------------------------------------------
+
+#if MIN_VERSION_base(4,7,0)
+instance FromJSON a => FromJSON (PM.Array a) where
+  -- note: we could do better than this if vector exposed the data
+  -- constructor in Data.Vector.
+  parseJSON = fmap Exts.fromList . parseJSON
+
+instance FromJSON a => FromJSON (PM.SmallArray a) where
+  parseJSON = fmap Exts.fromList . parseJSON
+
+#if MIN_VERSION_primitive(0,6,4)
+instance (PM.Prim a,FromJSON a) => FromJSON (PM.PrimArray a) where
+  parseJSON = fmap Exts.fromList . parseJSON
+
+instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
+  parseJSON = fmap Exts.fromList . parseJSON
+#endif
+#endif
 
 -------------------------------------------------------------------------------
 -- time
diff --git a/Data/Aeson/Types/Generic.hs b/Data/Aeson/Types/Generic.hs
--- a/Data/Aeson/Types/Generic.hs
+++ b/Data/Aeson/Types/Generic.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}
@@ -25,7 +26,7 @@
 
 module Data.Aeson.Types.Generic
     (
-      IsRecord(..)
+      IsRecord
     , AllNullary
     , Tagged2(..)
     , True
@@ -36,7 +37,6 @@
     , ProductSize(..)
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import GHC.Generics
diff --git a/Data/Aeson/Types/Internal.hs b/Data/Aeson/Types/Internal.hs
--- a/Data/Aeson/Types/Internal.hs
+++ b/Data/Aeson/Types/Internal.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE Rank2Types #-}
 #if __GLASGOW_HASKELL__ >= 800
 -- a) THQ works on cross-compilers and unregisterised GHCs
@@ -74,7 +75,6 @@
     , DotNetTime(..)
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative (Alternative(..))
@@ -331,8 +331,7 @@
 apP :: Parser (a -> b) -> Parser a -> Parser b
 apP d e = do
   b <- d
-  a <- e
-  return (b a)
+  b <$> e
 {-# INLINE apP #-}
 
 -- | A JSON \"object\" (key\/value map).
diff --git a/Data/Aeson/Types/ToJSON.hs b/Data/Aeson/Types/ToJSON.hs
--- a/Data/Aeson/Types/ToJSON.hs
+++ b/Data/Aeson/Types/ToJSON.hs
@@ -7,6 +7,7 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards #-}
 {-# LANGUAGE RecordWildCards #-}
@@ -58,7 +59,6 @@
     , listValue
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative (Const(..))
@@ -66,7 +66,7 @@
 import Data.Aeson.Encoding (Encoding, Encoding', Series, dict, emptyArray_)
 import Data.Aeson.Encoding.Internal ((>*<))
 import Data.Aeson.Internal.Functions (mapHashKeyVal, mapKeyVal)
-import Data.Aeson.Types.Generic (AllNullary, False, IsRecord(..), One, ProductSize, Tagged2(..), True, Zero, productSize)
+import Data.Aeson.Types.Generic (AllNullary, False, IsRecord, One, ProductSize, Tagged2(..), True, Zero, productSize)
 import Data.Aeson.Types.Internal
 import Data.Attoparsec.Number (Number(..))
 import Data.Bits (unsafeShiftR)
@@ -91,6 +91,7 @@
 import Data.Time.Locale.Compat (defaultTimeLocale)
 import Data.Vector (Vector)
 import Data.Version (Version, showVersion)
+import Data.Void (Void, absurd)
 import Data.Word (Word16, Word32, Word64, Word8)
 import Foreign.Storable (Storable)
 import Foreign.C.Types (CTime (..))
@@ -127,6 +128,16 @@
 import qualified Data.Aeson.Encoding.Builder as EB
 import qualified Data.ByteString.Builder as B
 
+import qualified GHC.Exts as Exts
+import qualified Data.Primitive.Array as PM
+import qualified Data.Primitive.SmallArray as PM
+import qualified Data.Primitive.Types as PM
+
+#if MIN_VERSION_primitive(0,6,4)
+import qualified Data.Primitive.UnliftedArray as PM
+import qualified Data.Primitive.PrimArray as PM
+#endif
+
 #if !(MIN_VERSION_bytestring(0,10,0))
 import Foreign.ForeignPtr (withForeignPtr)
 import Foreign.Marshal.Utils (copyBytes)
@@ -264,7 +275,7 @@
 -- @
 --
 -- Previous versions of this library only had the 'toJSON' method. Adding
--- 'toEncoding' had to reasons:
+-- 'toEncoding' had two reasons:
 --
 -- 1. toEncoding is more efficient for the common case that the output of
 -- 'toJSON' is directly serialized to a @ByteString@.
@@ -657,11 +668,13 @@
 instance OVERLAPPABLE_ (GToJSON enc arity a) => GToJSON enc arity (M1 i c a) where
     -- Meta-information, which is not handled elsewhere, is ignored:
     gToJSON opts targs = gToJSON opts targs . unM1
+    {-# INLINE gToJSON #-}
 
 instance GToJSON enc One Par1 where
     -- Direct occurrences of the last type parameter are encoded with the
     -- function passed in as an argument:
     gToJSON _opts (To1Args tj _) = tj . unPar1
+    {-# INLINE gToJSON #-}
 
 instance ( ConsToJSON enc arity a
          , AllNullary          (C1 c a) allNullary
@@ -674,11 +687,13 @@
                                      . sumToJSON opts targs
                                      . unM1
         | otherwise = consToJSON opts targs . unM1 . unM1
+    {-# INLINE gToJSON #-}
 
 instance (ConsToJSON enc arity a) => GToJSON enc arity (C1 c a) where
     -- Constructors need to be encoded differently depending on whether they're
     -- a record or not. This distinction is made by 'consToJSON':
     gToJSON opts targs = consToJSON opts targs . unM1
+    {-# INLINE gToJSON #-}
 
 instance ( AllNullary       (a :+: b) allNullary
          , SumToJSON  enc arity (a :+: b) allNullary
@@ -689,6 +704,7 @@
     -- strings.  This distinction is made by 'sumToJSON':
     gToJSON opts targs = (unTagged :: Tagged allNullary enc -> enc)
                        . sumToJSON opts targs
+    {-# INLINE gToJSON #-}
 
 --------------------------------------------------------------------------------
 -- Generic toJSON
@@ -697,18 +713,27 @@
 -- possible but makes error messages a bit harder to understand for missing
 -- instances.
 
+instance GToJSON Value arity V1 where
+    -- Empty values do not exist, which makes the job of formatting them
+    -- rather easy:
+    gToJSON _ _ x = x `seq` error "case: V1"
+    {-# INLINE gToJSON #-}
+
 instance ToJSON a => GToJSON Value arity (K1 i a) where
     -- Constant values are encoded using their ToJSON instance:
     gToJSON _opts _ = toJSON . unK1
+    {-# INLINE gToJSON #-}
 
 instance ToJSON1 f => GToJSON Value One (Rec1 f) where
     -- Recursive occurrences of the last type parameter are encoded using their
     -- ToJSON1 instance:
     gToJSON _opts (To1Args tj tjl) = liftToJSON tj tjl . unRec1
+    {-# INLINE gToJSON #-}
 
 instance GToJSON Value arity U1 where
     -- Empty constructors are encoded to an empty array:
     gToJSON _opts _ _ = emptyArray
+    {-# INLINE gToJSON #-}
 
 instance ( WriteProduct arity a, WriteProduct arity b
          , ProductSize        a, ProductSize        b
@@ -725,6 +750,7 @@
         where
           lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)
                        productSize
+    {-# INLINE gToJSON #-}
 
 instance ( ToJSON1 f
          , GToJSON Value One g
@@ -736,6 +762,7 @@
     gToJSON opts targs =
       let gtj = gToJSON opts targs in
       liftToJSON gtj (listValue gtj) . unComp1
+    {-# INLINE gToJSON #-}
 
 --------------------------------------------------------------------------------
 -- Generic toEncoding
@@ -743,15 +770,18 @@
 instance ToJSON a => GToJSON Encoding arity (K1 i a) where
     -- Constant values are encoded using their ToJSON instance:
     gToJSON _opts _ = toEncoding . unK1
+    {-# INLINE gToJSON #-}
 
 instance ToJSON1 f => GToJSON Encoding One (Rec1 f) where
     -- Recursive occurrences of the last type parameter are encoded using their
     -- ToEncoding1 instance:
     gToJSON _opts (To1Args te tel) = liftToEncoding te tel . unRec1
+    {-# INLINE gToJSON #-}
 
 instance GToJSON Encoding arity U1 where
     -- Empty constructors are encoded to an empty array:
     gToJSON _opts _ _ = E.emptyArray_
+    {-# INLINE gToJSON #-}
 
 instance ( EncodeProduct  arity a
          , EncodeProduct  arity b
@@ -761,6 +791,7 @@
     -- the same size as the product and write the product's elements to it using
     -- 'encodeProduct':
     gToJSON opts targs p = E.list E.retagEncoding [encodeProduct opts targs p]
+    {-# INLINE gToJSON #-}
 
 instance ( ToJSON1 f
          , GToJSON Encoding One g
@@ -772,6 +803,7 @@
     gToJSON opts targs =
       let gte = gToJSON opts targs in
       liftToEncoding gte (listEncoding gte) . unComp1
+    {-# INLINE gToJSON #-}
 
 --------------------------------------------------------------------------------
 
@@ -983,6 +1015,7 @@
          ) => ConsToJSON' enc arity f True
   where
     consToJSON' opts targs = Tagged . fromPairs . recordToPairs opts targs
+    {-# INLINE consToJSON' #-}
 
 instance GToJSON enc arity f => ConsToJSON' enc arity f False where
     consToJSON' opts targs = Tagged . gToJSON opts targs
@@ -1074,10 +1107,12 @@
           lenL = len `unsafeShiftR` 1
           lenR = len - lenL
           ixR  = ix  + lenL
+    {-# INLINE writeProduct #-}
 
 instance OVERLAPPABLE_ (GToJSON Value arity a) => WriteProduct arity a where
     writeProduct opts targs mv ix _ =
       VM.unsafeWrite mv ix . gToJSON opts targs
+    {-# INLINE writeProduct #-}
 
 --------------------------------------------------------------------------------
 
@@ -1095,9 +1130,11 @@
     encodeProduct opts targs (a :*: b) =
       encodeProduct opts targs a >*<
       encodeProduct opts targs b
+    {-# INLINE encodeProduct #-}
 
 instance OVERLAPPABLE_ (GToJSON Encoding arity a) => EncodeProduct arity a where
     encodeProduct opts targs a = E.retagEncoding $ gToJSON opts targs a
+    {-# INLINE encodeProduct #-}
 
 --------------------------------------------------------------------------------
 
@@ -1201,7 +1238,14 @@
     toEncoding = toEncoding2
     {-# INLINE toEncoding #-}
 
+instance ToJSON Void where
+    toJSON = absurd
+    {-# INLINE toJSON #-}
 
+    toEncoding = absurd
+    {-# INLINE toEncoding #-}
+
+
 instance ToJSON Bool where
     toJSON = Bool
     {-# INLINE toJSON #-}
@@ -1883,6 +1927,32 @@
 
 formatMillis :: (FormatTime t) => t -> String
 formatMillis = take 3 . formatTime defaultTimeLocale "%q"
+
+-------------------------------------------------------------------------------
+-- primitive
+-------------------------------------------------------------------------------
+
+#if MIN_VERSION_base(4,7,0)
+instance ToJSON a => ToJSON (PM.Array a) where
+  -- note: we could do better than this if vector exposed the data
+  -- constructor in Data.Vector.
+  toJSON = toJSON . Exts.toList
+  toEncoding = toEncoding . Exts.toList
+
+instance ToJSON a => ToJSON (PM.SmallArray a) where
+  toJSON = toJSON . Exts.toList
+  toEncoding = toEncoding . Exts.toList
+
+#if (MIN_VERSION_primitive(0,6,4))
+instance (PM.Prim a,ToJSON a) => ToJSON (PM.PrimArray a) where
+  toJSON = toJSON . Exts.toList
+  toEncoding = toEncoding . Exts.toList
+
+instance (PM.PrimUnlifted a,ToJSON a) => ToJSON (PM.UnliftedArray a) where
+  toJSON = toJSON . Exts.toList
+  toEncoding = toEncoding . Exts.toList
+#endif
+#endif
 
 -------------------------------------------------------------------------------
 -- time
diff --git a/aeson.cabal b/aeson.cabal
--- a/aeson.cabal
+++ b/aeson.cabal
@@ -1,5 +1,5 @@
 name:            aeson
-version:         1.4.0.0
+version:         1.4.1.0
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Web, JSON
@@ -108,6 +108,7 @@
     dlist >= 0.6,
     ghc-prim >= 0.2,
     hashable >= 1.1.2.0,
+    primitive >= 0.6.1,
     scientific >= 0.3.4.7 && < 0.4,
     tagged >=0.8.3 && <0.9,
     template-haskell >= 2.7,
@@ -135,7 +136,8 @@
 
   if !impl(ghc >= 7.10)
     -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8
-    build-depends: nats >= 1 && < 1.2
+    build-depends: nats >= 1 && < 1.2,
+                   void >= 0.7.2 && < 0.8
 
   ghc-options: -Wall
 
@@ -227,7 +229,8 @@
       transformers-compat >= 0.3
 
   if !impl(ghc >= 7.10)
-    build-depends: nats >=1 && <1.2
+    build-depends: nats >=1 && <1.2,
+                   void >=0.7.2 && <0.8
 
   if impl(ghc >= 7.8)
     build-depends: hashable-time >= 0.2 && <0.3
diff --git a/attoparsec-iso8601/Data/Attoparsec/Time.hs b/attoparsec-iso8601/Data/Attoparsec/Time.hs
--- a/attoparsec-iso8601/Data/Attoparsec/Time.hs
+++ b/attoparsec-iso8601/Data/Attoparsec/Time.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-
 -- |
 -- Module:      Data.Aeson.Parser.Time
 -- Copyright:   (c) 2015-2016 Bryan O'Sullivan
@@ -21,7 +21,6 @@
     , zonedTime
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative ((<|>))
diff --git a/attoparsec-iso8601/Data/Attoparsec/Time/Internal.hs b/attoparsec-iso8601/Data/Attoparsec/Time/Internal.hs
--- a/attoparsec-iso8601/Data/Attoparsec/Time/Internal.hs
+++ b/attoparsec-iso8601/Data/Attoparsec/Time/Internal.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE CPP #-}
-
+{-# LANGUAGE NoImplicitPrelude #-}
 -- |
 -- Module:      Data.Aeson.Internal.Time
 -- Copyright:   (c) 2015-2016 Bryan O'Sullivan
@@ -17,17 +17,37 @@
     , toTimeOfDay64
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Int (Int64)
 import Data.Time
 import Unsafe.Coerce (unsafeCoerce)
 
+#if MIN_VERSION_time(1,6,0)
+
+import Data.Time.Clock (diffTimeToPicoseconds)
+
+#endif
+
 #if MIN_VERSION_base(4,7,0)
 
 import Data.Fixed (Pico, Fixed(MkFixed))
 
+#else
+
+import Data.Fixed (Pico)
+
+#endif
+
+#if !MIN_VERSION_time(1,6,0)
+
+diffTimeToPicoseconds :: DiffTime -> Integer
+diffTimeToPicoseconds = unsafeCoerce
+
+#endif
+
+#if MIN_VERSION_base(4,7,0)
+
 toPico :: Integer -> Pico
 toPico = MkFixed
 
@@ -36,8 +56,6 @@
 
 #else
 
-import Data.Fixed (Pico)
-
 toPico :: Integer -> Pico
 toPico = unsafeCoerce
 
@@ -51,11 +69,16 @@
                        {-# UNPACK #-} !Int
                        {-# UNPACK #-} !Int64
 
+posixDayLength :: DiffTime
+posixDayLength = 86400
+
 diffTimeOfDay64 :: DiffTime -> TimeOfDay64
-diffTimeOfDay64 t = TOD (fromIntegral h) (fromIntegral m) s
-  where (h,mp) = fromIntegral pico `quotRem` 3600000000000000
-        (m,s)  = mp `quotRem` 60000000000000
-        pico   = unsafeCoerce t :: Integer
+diffTimeOfDay64 t
+  | t >= posixDayLength = TOD 23 59 (60000000000000 + pico (t - posixDayLength))
+  | otherwise = TOD (fromIntegral h) (fromIntegral m) s
+    where (h,mp) = pico t `quotRem` 3600000000000000
+          (m,s)  = mp `quotRem` 60000000000000
+          pico   = fromIntegral . diffTimeToPicoseconds
 
 toTimeOfDay64 :: TimeOfDay -> TimeOfDay64
 toTimeOfDay64 (TimeOfDay h m s) = TOD h m (fromIntegral (fromPico s))
diff --git a/benchmarks/AesonEncode.hs b/benchmarks/AesonEncode.hs
--- a/benchmarks/AesonEncode.hs
+++ b/benchmarks/AesonEncode.hs
@@ -1,9 +1,9 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.DeepSeq
diff --git a/benchmarks/AesonFoldable.hs b/benchmarks/AesonFoldable.hs
--- a/benchmarks/AesonFoldable.hs
+++ b/benchmarks/AesonFoldable.hs
@@ -1,10 +1,10 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main (main) where
 
 import Criterion.Main
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Foldable (toList)
diff --git a/benchmarks/AesonMap.hs b/benchmarks/AesonMap.hs
--- a/benchmarks/AesonMap.hs
+++ b/benchmarks/AesonMap.hs
@@ -1,11 +1,11 @@
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE RankNTypes #-}
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.DeepSeq
diff --git a/benchmarks/AesonParse.hs b/benchmarks/AesonParse.hs
--- a/benchmarks/AesonParse.hs
+++ b/benchmarks/AesonParse.hs
@@ -1,9 +1,9 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson
diff --git a/benchmarks/AesonTuples.hs b/benchmarks/AesonTuples.hs
--- a/benchmarks/AesonTuples.hs
+++ b/benchmarks/AesonTuples.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.DeepSeq (deepseq)
diff --git a/benchmarks/Compare.hs b/benchmarks/Compare.hs
--- a/benchmarks/Compare.hs
+++ b/benchmarks/Compare.hs
@@ -1,8 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Compare.BufferBuilder ()
diff --git a/benchmarks/Compare/BufferBuilder.hs b/benchmarks/Compare/BufferBuilder.hs
--- a/benchmarks/Compare/BufferBuilder.hs
+++ b/benchmarks/Compare/BufferBuilder.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
@@ -6,7 +7,6 @@
 
 module Compare.BufferBuilder () where
 
-import Prelude ()
 import Prelude.Compat hiding ((<>))
 
 import Data.BufferBuilder.Json
diff --git a/benchmarks/Compare/JsonBench.hs b/benchmarks/Compare/JsonBench.hs
--- a/benchmarks/Compare/JsonBench.hs
+++ b/benchmarks/Compare/JsonBench.hs
@@ -1,16 +1,16 @@
--- Adapted from a buffer-builder benchmark:
---
--- https://github.com/chadaustin/buffer-builder/blob/master/test.json
-
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE MagicHash #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
+-- Adapted from a buffer-builder benchmark:
+--
+-- https://github.com/chadaustin/buffer-builder/blob/master/test.json
+
 module Compare.JsonBench (benchmarks) where
 
-import Prelude ()
 import Prelude.Compat hiding ((<>))
 
 import Control.DeepSeq (NFData(..))
diff --git a/benchmarks/Compare/JsonBuilder.hs b/benchmarks/Compare/JsonBuilder.hs
--- a/benchmarks/Compare/JsonBuilder.hs
+++ b/benchmarks/Compare/JsonBuilder.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE RecordWildCards #-}
 
 {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
@@ -5,7 +6,6 @@
 
 module Compare.JsonBuilder () where
 
-import Prelude ()
 import Prelude.Compat hiding ((<>))
 
 import Data.Json.Builder
diff --git a/benchmarks/CompareWithJSON.hs b/benchmarks/CompareWithJSON.hs
--- a/benchmarks/CompareWithJSON.hs
+++ b/benchmarks/CompareWithJSON.hs
@@ -1,8 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Blaze.ByteString.Builder (toLazyByteString)
diff --git a/benchmarks/Dates.hs b/benchmarks/Dates.hs
--- a/benchmarks/Dates.hs
+++ b/benchmarks/Dates.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Criterion.Main
diff --git a/benchmarks/Escape.hs b/benchmarks/Escape.hs
--- a/benchmarks/Escape.hs
+++ b/benchmarks/Escape.hs
@@ -1,9 +1,10 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+
 {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Criterion.Main
diff --git a/benchmarks/JsonParse.hs b/benchmarks/JsonParse.hs
--- a/benchmarks/JsonParse.hs
+++ b/benchmarks/JsonParse.hs
@@ -1,10 +1,11 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.DeepSeq
diff --git a/benchmarks/Micro.hs b/benchmarks/Micro.hs
--- a/benchmarks/Micro.hs
+++ b/benchmarks/Micro.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Criterion.Main
diff --git a/benchmarks/ReadFile.hs b/benchmarks/ReadFile.hs
--- a/benchmarks/ReadFile.hs
+++ b/benchmarks/ReadFile.hs
@@ -1,9 +1,9 @@
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.DeepSeq
diff --git a/benchmarks/Typed.hs b/benchmarks/Typed.hs
--- a/benchmarks/Typed.hs
+++ b/benchmarks/Typed.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Criterion.Main
diff --git a/benchmarks/Typed/Common.hs b/benchmarks/Typed/Common.hs
--- a/benchmarks/Typed/Common.hs
+++ b/benchmarks/Typed/Common.hs
@@ -1,8 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 {-# OPTIONS_GHC -fno-warn-unused-imports #-}
 
 module Typed.Common (load) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.ByteString.Lazy as L
diff --git a/benchmarks/Typed/Generic.hs b/benchmarks/Typed/Generic.hs
--- a/benchmarks/Typed/Generic.hs
+++ b/benchmarks/Typed/Generic.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Typed.Generic (benchmarks, decodeBenchmarks) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson hiding (Result)
diff --git a/benchmarks/Typed/Manual.hs b/benchmarks/Typed/Manual.hs
--- a/benchmarks/Typed/Manual.hs
+++ b/benchmarks/Typed/Manual.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Typed.Manual (benchmarks, decodeBenchmarks) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson hiding (Result)
diff --git a/benchmarks/Typed/TH.hs b/benchmarks/Typed/TH.hs
--- a/benchmarks/Typed/TH.hs
+++ b/benchmarks/Typed/TH.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Typed.TH (benchmarks, decodeBenchmarks) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson hiding (Result)
diff --git a/benchmarks/aeson-benchmarks.cabal b/benchmarks/aeson-benchmarks.cabal
--- a/benchmarks/aeson-benchmarks.cabal
+++ b/benchmarks/aeson-benchmarks.cabal
@@ -39,6 +39,7 @@
       ghc-prim >= 0.2,
       hashable >= 1.1.2.0,
       mtl,
+      primitive >= 0.6.1,
       scientific >= 0.3.4.7 && < 0.4,
       syb,
       tagged >=0.8.3 && <0.9,
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,15 @@
 For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md).
 
+#### 1.4.1.0
+
+* Optimizations of generics, thanks to Rémy Oudompheng, here are some numbers for GHC 8.4:
+  * Compilation time: G/BigProduct.hs is 25% faster, G/BigRecord.hs is 2x faster.
+  * Runtime performance: BigRecord/toJSON/generic and BigProduct/encode/generic are more than 2x faster.
+* Added To/FromJSON instances for `Void` and Generics's `V1`, thanks to Will Yager
+* Added To/FromJSON instances for `primitive`'s `Array`, `SmallArray`, `PrimArray` and `UnliftedArray`, thanks to Andrew Thad.
+* Fixes handling of `UTCTime` wrt. leap seconds , thanks to Adam Schønemann
+* Warning and documentation fixes thanks to tom-bop, Gabor Greif, Ian Jeffries, and Mateusz Curyło.
+
 ### 1.4.0.0
 
 This release introduces bounds on the size of `Scientific` numbers when they are converted to other arbitrary precision types that do not represent them efficiently in memory.
diff --git a/examples/Generic.hs b/examples/Generic.hs
--- a/examples/Generic.hs
+++ b/examples/Generic.hs
@@ -6,11 +6,11 @@
 -- automatically derive the Generic class for us.
 
 {-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson (FromJSON, ToJSON, decode, encode)
diff --git a/examples/Simplest.hs b/examples/Simplest.hs
--- a/examples/Simplest.hs
+++ b/examples/Simplest.hs
@@ -1,9 +1,9 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative (empty)
diff --git a/examples/TemplateHaskell.hs b/examples/TemplateHaskell.hs
--- a/examples/TemplateHaskell.hs
+++ b/examples/TemplateHaskell.hs
@@ -1,12 +1,12 @@
 -- We can use Template Haskell (TH) to generate instances of the
 -- FromJSON and ToJSON classes automatically.  This is the fastest way
 -- to add JSON support for a type.
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson (decode, encode)
diff --git a/examples/Twitter.hs b/examples/Twitter.hs
--- a/examples/Twitter.hs
+++ b/examples/Twitter.hs
@@ -10,6 +10,7 @@
 
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
 module Twitter
     (
@@ -19,7 +20,6 @@
     , Result(..)
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.DeepSeq
diff --git a/examples/Twitter/Generic.hs b/examples/Twitter/Generic.hs
--- a/examples/Twitter/Generic.hs
+++ b/examples/Twitter/Generic.hs
@@ -1,5 +1,7 @@
 -- Use GHC generics to automatically generate good instances.
 
+{-# LANGUAGE NoImplicitPrelude #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Twitter.Generic
@@ -10,7 +12,6 @@
     , Result(..)
     ) where
 
-import Prelude ()
 import Prelude.Compat ()
 
 import Twitter
diff --git a/examples/Twitter/Manual.hs b/examples/Twitter/Manual.hs
--- a/examples/Twitter/Manual.hs
+++ b/examples/Twitter/Manual.hs
@@ -1,7 +1,8 @@
 -- Manually write instances.
-
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Twitter.Manual
@@ -12,7 +13,6 @@
     , Result(..)
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative
diff --git a/examples/Twitter/TH.hs b/examples/Twitter/TH.hs
--- a/examples/Twitter/TH.hs
+++ b/examples/Twitter/TH.hs
@@ -1,6 +1,8 @@
 -- Use Template Haskell to generate good instances.
 
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TemplateHaskell #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Twitter.TH
@@ -11,7 +13,6 @@
     , Result(..)
     ) where
 
-import Prelude ()
 
 import Twitter
 import Twitter.Options
diff --git a/stack-lts6.yaml b/stack-lts6.yaml
--- a/stack-lts6.yaml
+++ b/stack-lts6.yaml
@@ -3,7 +3,6 @@
 - '.'
 - attoparsec-iso8601
 extra-deps:
-- integer-logarithms-1
 - semigroups-0.18.2
 - tagged-0.8.5
 - transformers-compat-0.5.1.4
@@ -13,6 +12,7 @@
 - integer-logarithms-1
 - quickcheck-instances-0.3.16
 - th-abstraction-0.2.2.0
+- text-1.2.3.0
 flags:
 flags:
   aeson:
diff --git a/stack-lts7.yaml b/stack-lts7.yaml
--- a/stack-lts7.yaml
+++ b/stack-lts7.yaml
@@ -9,6 +9,7 @@
 - integer-logarithms-1
 - quickcheck-instances-0.3.16
 - th-abstraction-0.2.2.0
+- text-1.2.3.0
 flags:
   aeson:
     fast: true
diff --git a/tests/DataFamilies/Encoders.hs b/tests/DataFamilies/Encoders.hs
--- a/tests/DataFamilies/Encoders.hs
+++ b/tests/DataFamilies/Encoders.hs
@@ -1,10 +1,10 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module DataFamilies.Encoders (module DataFamilies.Encoders) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.TH
diff --git a/tests/DataFamilies/Instances.hs b/tests/DataFamilies/Instances.hs
--- a/tests/DataFamilies/Instances.hs
+++ b/tests/DataFamilies/Instances.hs
@@ -1,12 +1,13 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module DataFamilies.Instances () where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.TH
diff --git a/tests/DataFamilies/Properties.hs b/tests/DataFamilies/Properties.hs
--- a/tests/DataFamilies/Properties.hs
+++ b/tests/DataFamilies/Properties.hs
@@ -1,8 +1,8 @@
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
 module DataFamilies.Properties (tests) where
 
-import Prelude ()
 import Prelude.Compat
 
 import DataFamilies.Encoders
diff --git a/tests/DataFamilies/Types.hs b/tests/DataFamilies/Types.hs
--- a/tests/DataFamilies/Types.hs
+++ b/tests/DataFamilies/Types.hs
@@ -4,13 +4,13 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
 
 module DataFamilies.Types (module DataFamilies.Types) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Generics.Deriving.TH (deriveAll0)
diff --git a/tests/Encoders.hs b/tests/Encoders.hs
--- a/tests/Encoders.hs
+++ b/tests/Encoders.hs
@@ -1,10 +1,10 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module Encoders (module Encoders) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.TH
diff --git a/tests/ErrorMessages.hs b/tests/ErrorMessages.hs
--- a/tests/ErrorMessages.hs
+++ b/tests/ErrorMessages.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
@@ -6,7 +7,6 @@
     tests
   ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson (FromJSON(..), eitherDecode)
diff --git a/tests/Functions.hs b/tests/Functions.hs
--- a/tests/Functions.hs
+++ b/tests/Functions.hs
@@ -1,10 +1,11 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Functions
     (
       approxEq
     , approxEqWith
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 approxEq :: (Fractional a, Ord a) => a -> a -> Bool
diff --git a/tests/Instances.hs b/tests/Instances.hs
--- a/tests/Instances.hs
+++ b/tests/Instances.hs
@@ -1,13 +1,14 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
+
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Instances () where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative (empty)
diff --git a/tests/Options.hs b/tests/Options.hs
--- a/tests/Options.hs
+++ b/tests/Options.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Options (module Options) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson.Types
diff --git a/tests/Properties.hs b/tests/Properties.hs
--- a/tests/Properties.hs
+++ b/tests/Properties.hs
@@ -1,12 +1,12 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-} -- For arbitrary Compose
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Properties (module Properties) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative (Const)
diff --git a/tests/SerializationFormatSpec.hs b/tests/SerializationFormatSpec.hs
--- a/tests/SerializationFormatSpec.hs
+++ b/tests/SerializationFormatSpec.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 #if __GLASGOW_HASKELL__ >= 708
 {-# LANGUAGE DataKinds #-}
@@ -15,7 +16,6 @@
     tests
   ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Applicative (Const(..))
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -1,6 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
 module Main (main) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Test.Tasty (defaultMain, testGroup)
diff --git a/tests/Types.hs b/tests/Types.hs
--- a/tests/Types.hs
+++ b/tests/Types.hs
@@ -4,15 +4,16 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
 
 module Types (module Types) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Math.NumberTheory.Logarithms (intLog2)
+import Control.Applicative ((<$>))
 import Data.Data
 import Data.Functor.Compose (Compose (..))
 import Data.Functor.Identity (Identity (..))
@@ -152,7 +153,7 @@
     hashWithSalt salt (LogScaled a) = hashWithSalt salt a
 
 instance Arbitrary a => Arbitrary (LogScaled a) where
-    arbitrary = fmap LogScaled $ scale (\x -> intLog2 $ x + 1) arbitrary
+    arbitrary = LogScaled <$> scale (\x -> intLog2 $ x + 1) arbitrary
     shrink = fmap LogScaled . shrink . getLogScaled
 
 instance ToJSON a => ToJSON (LogScaled a) where
diff --git a/tests/UnitTests.hs b/tests/UnitTests.hs
--- a/tests/UnitTests.hs
+++ b/tests/UnitTests.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskell #-}
@@ -19,7 +20,6 @@
     , withEmbeddedJSONTest
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Control.Monad (forM, forM_)
@@ -199,6 +199,14 @@
   assertEqual "utctime" (parseWithRead "%F %H:%MZ" ts11) t11
   assertEqual "utctime" (parseWithRead "%FT%T%QZ" "2015-01-01T14:30:00Z") t12
 
+  -- leap seconds are included correctly
+  let ts13 = "2015-08-23T23:59:60.128+00" :: LT.Text
+  let (Just (t13 ::  UTCTime)) = parseWithAeson ts13
+  assertEqual "utctime" (parseWithRead "%FT%T%QZ" "2015-08-23T23:59:60.128Z") t13
+  let ts14 = "2015-08-23T23:59:60.999999999999+00" :: LT.Text
+  let (Just (t14 ::  UTCTime)) = parseWithAeson ts14
+  assertEqual "utctime" (parseWithRead "%FT%T%QZ" "2015-08-23T23:59:60.999999999999Z") t14
+
   where
     parseWithRead :: String -> LT.Text -> UTCTime
     parseWithRead f s =
@@ -218,6 +226,7 @@
   verifyFailParse "2015-01-01T12:30:00.00+00:00Z" -- no Zulu if offset given
   verifyFailParse "2015-01-03 12:13:00.Z" -- decimal at the end but no digits
   verifyFailParse "2015-01-03 12:13.000Z" -- decimal at the end, but no seconds
+  verifyFailParse "2015-01-03 23:59:61Z"  -- exceeds allowed seconds per day
   where
     verifyFailParse (s :: LT.Text) =
       let (dec :: Maybe UTCTime) = decode . LT.encodeUtf8 $ LT.concat ["\"", s, "\""] in
diff --git a/tests/UnitTests/NullaryConstructors.hs b/tests/UnitTests/NullaryConstructors.hs
--- a/tests/UnitTests/NullaryConstructors.hs
+++ b/tests/UnitTests/NullaryConstructors.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE  OverloadedStrings #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
 
 {-# OPTIONS_GHC -fno-warn-deprecations #-}
 
@@ -7,7 +8,6 @@
       nullaryConstructors
     ) where
 
-import Prelude ()
 import Prelude.Compat
 
 import Data.Aeson (decode, eitherDecode, fromEncoding, Value)
