Skip to content

Resolve build warnings #1564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions servant-client-core/servant-client-core.cabal
Original file line number Diff line number Diff line change
@@ -44,6 +44,8 @@ library

other-modules:
Servant.Client.Core.Internal
Servant.Client.Core.HasClient.Internal
Servant.Client.Core.HasClient.TypeErrors

-- Bundled with GHC: Lower bound to not force re-installs
-- text and mtl are bundled starting with GHC-8.4
1,001 changes: 8 additions & 993 deletions servant-client-core/src/Servant/Client/Core/HasClient.hs

Large diffs are not rendered by default.

975 changes: 975 additions & 0 deletions servant-client-core/src/Servant/Client/Core/HasClient/Internal.hs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}

-- | This module contains erroring instances for @Servant.Client.Core.HasClient.Internal@.
-- They are separated from the bulk of the code, because they raise "missing methods"
-- warnings. These warnings are expected, but ignoring them would lead to missing
-- relevant warnings in @Servant.Client.Core.HasClient.Internal@. Therefore, we put them
-- in a separate file, and ignore the warnings here.
module Servant.Client.Core.HasClient.TypeErrors ()
where

import Prelude ()
import Prelude.Compat

import GHC.TypeLits
(TypeError)
import Servant.API
((:>))
import Servant.API.TypeErrors

import Servant.Client.Core.HasClient.Internal
import Servant.Client.Core.RunClient

-- Erroring instance for HasClient' when a combinator is not fully applied
instance (RunClient m, TypeError (PartialApplication HasClient arr)) => HasClient m ((arr :: a -> b) :> sub)
where
type Client m (arr :> sub) = TypeError (PartialApplication HasClient arr)
clientWithRoute _ _ _ = error "unreachable"
hoistClientMonad _ _ _ _ = error "unreachable"

-- Erroring instances for 'HasClient' for unknown API combinators
instance {-# OVERLAPPABLE #-} (RunClient m, TypeError (NoInstanceForSub (HasClient m) ty)) => HasClient m (ty :> sub)

instance {-# OVERLAPPABLE #-} (RunClient m, TypeError (NoInstanceFor (HasClient m api))) => HasClient m api
6 changes: 2 additions & 4 deletions servant-client/src/Servant/Client/Internal/HttpClient.hs
Original file line number Diff line number Diff line change
@@ -43,14 +43,12 @@ import qualified Data.ByteString as BS
import Data.ByteString.Builder
(toLazyByteString)
import qualified Data.ByteString.Lazy as BSL
import Data.Either
(either)
import Data.Foldable
(foldl',toList)
import Data.Functor.Alt
(Alt (..))
import Data.Maybe
(maybe, maybeToList)
(maybeToList)
import Data.Proxy
(Proxy (..))
import Data.Sequence
@@ -63,7 +61,7 @@ import GHC.Generics
import Network.HTTP.Media
(renderHeader)
import Network.HTTP.Types
(hContentType, renderQuery, statusIsSuccessful, urlEncode, Status)
(hContentType, statusIsSuccessful, urlEncode, Status)
import Servant.Client.Core

import qualified Network.HTTP.Client as Client
Original file line number Diff line number Diff line change
@@ -24,8 +24,6 @@ import Control.DeepSeq
(NFData, force)
import Control.Exception
(evaluate, throwIO)
import Control.Monad
(unless)
import Control.Monad.Base
(MonadBase (..))
import Control.Monad.Codensity
68 changes: 2 additions & 66 deletions servant-client/test/Servant/StreamSpec.hs
Original file line number Diff line number Diff line change
@@ -21,16 +21,9 @@

module Servant.StreamSpec (spec) where

import Control.Monad
(when)
import Control.Monad.Codensity
(Codensity (..))
import Control.Monad.IO.Class
(MonadIO (..))
import Control.Monad.Trans.Except
import qualified Data.ByteString as BS
import Data.Proxy
import qualified Data.TDigest as TD
import qualified Network.HTTP.Client as C
import Prelude ()
import Prelude.Compat
@@ -46,20 +39,10 @@ import System.Entropy
(getEntropy, getHardwareEntropy)
import System.IO.Unsafe
(unsafePerformIO)
import System.Mem
(performGC)
import Test.Hspec
import Servant.ClientTestUtils (Person(..))
import qualified Servant.ClientTestUtils as CT

#if MIN_VERSION_base(4,10,0)
import GHC.Stats
(gc, gcdetails_live_bytes, getRTSStats)
#else
import GHC.Stats
(currentBytesUsed, getGCStats)
#endif

-- This declaration simply checks that all instances are in place.
-- Note: this is streaming client
_ = client comprehensiveAPI
@@ -78,9 +61,9 @@ api :: Proxy StreamApi
api = Proxy

getGetNL, getGetNS :: ClientM (SourceIO Person)
getGetALot :: ClientM (SourceIO BS.ByteString)
_getGetALot :: ClientM (SourceIO BS.ByteString)
getStreamBody :: SourceT IO BS.ByteString -> ClientM (SourceIO BS.ByteString)
getGetNL :<|> getGetNS :<|> getGetALot :<|> getStreamBody = client api
getGetNL :<|> getGetNS :<|> _getGetALot :<|> getStreamBody = client api

alice :: Person
alice = Person "Alice" 42
@@ -134,50 +117,3 @@ streamSpec = beforeAll (CT.startWaiApp server) $ afterAll CT.endWaiApp $ do
where
input = ["foo", "", "bar"]
output = ["foo", "bar"]

{-
it "streams in constant memory" $ \(_, baseUrl) -> do
Right rs <- runClient getGetALot baseUrl
performGC
-- usage0 <- getUsage
-- putStrLn $ "Start: " ++ show usage0
tdigest <- memoryUsage $ joinCodensitySourceT rs
-- putStrLn $ "Median: " ++ show (TD.median tdigest)
-- putStrLn $ "Mean: " ++ show (TD.mean tdigest)
-- putStrLn $ "Stddev: " ++ show (TD.stddev tdigest)
-- forM_ [0.01, 0.1, 0.2, 0.5, 0.8, 0.9, 0.99] $ \q ->
-- putStrLn $ "q" ++ show q ++ ": " ++ show (TD.quantile q tdigest)
let Just stddev = TD.stddev tdigest
-- standard deviation of 100k is ok, we generate 256M of data after all.
-- On my machine deviation is 40k-50k
stddev `shouldSatisfy` (< 100000)
memoryUsage :: SourceT IO BS.ByteString -> IO (TD.TDigest 25)
memoryUsage src = unSourceT src $ loop mempty (0 :: Int)
where
loop !acc !_ Stop = return acc
loop !_ !_ (Error err) = fail err -- !
loop !acc !n (Skip s) = loop acc n s
loop !acc !n (Effect ms) = ms >>= loop acc n
loop !acc !n (Yield _bs s) = do
usage <- liftIO getUsage
-- We perform GC in between as we generate garbage.
when (n `mod` 1024 == 0) $ liftIO performGC
loop (TD.insert usage acc) (n + 1) s
getUsage :: IO Double
getUsage = fromIntegral .
#if MIN_VERSION_base(4,10,0)
gcdetails_live_bytes . gc <$> getRTSStats
#else
currentBytesUsed <$> getGCStats
#endif
memUsed `shouldSatisfy` (< megabytes 22)
megabytes :: Num a => a -> a
megabytes n = n * (1000 ^ (2 :: Int))
-}
2 changes: 0 additions & 2 deletions servant-conduit/example/Main.hs
Original file line number Diff line number Diff line change
@@ -17,8 +17,6 @@ import Data.Maybe
(fromMaybe)
import Network.HTTP.Client
(defaultManagerSettings, newManager)
import Network.Wai
(Application)
import System.Environment
(getArgs, lookupEnv)
import Text.Read
6 changes: 3 additions & 3 deletions servant-docs/src/Servant/Docs/Internal.hs
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ import Data.String.Conversions
import Data.Text
(Text, unpack)
import GHC.Generics
(Generic, Rep, K1(K1), M1(M1), U1(U1), V1,
(K1(K1), M1(M1), U1(U1), V1,
(:*:)((:*:)), (:+:)(L1, R1))
import qualified GHC.Generics as G
import GHC.TypeLits
@@ -964,7 +964,7 @@ instance {-# OVERLAPPABLE #-}

instance (ReflectMethod method) =>
HasDocs (NoContentVerb method) where
docsFor Proxy (endpoint, action) DocOptions{..} =
docsFor Proxy (endpoint, action) _ =
single endpoint' action'

where endpoint' = endpoint & method .~ method'
@@ -982,7 +982,7 @@ instance (ReflectMethod method) =>
instance {-# OVERLAPPABLE #-}
(Accept ct, KnownNat status, ReflectMethod method)
=> HasDocs (Stream method status framing ct a) where
docsFor Proxy (endpoint, action) DocOptions{..} =
docsFor Proxy (endpoint, action) _ =
single endpoint' action'

where endpoint' = endpoint & method .~ method'
2 changes: 0 additions & 2 deletions servant-machines/example/Main.hs
Original file line number Diff line number Diff line change
@@ -17,8 +17,6 @@ import Data.Void
(Void)
import Network.HTTP.Client
(defaultManagerSettings, newManager)
import Network.Wai
(Application)
import System.Environment
(getArgs, lookupEnv)
import Text.Read
2 changes: 0 additions & 2 deletions servant-pipes/example/Main.hs
Original file line number Diff line number Diff line change
@@ -15,8 +15,6 @@ import Data.Maybe
(fromMaybe)
import Network.HTTP.Client
(defaultManagerSettings, newManager)
import Network.Wai
(Application)
import System.Environment
(getArgs, lookupEnv)
import System.IO
3 changes: 3 additions & 0 deletions servant-server/servant-server.cabal
Original file line number Diff line number Diff line change
@@ -53,6 +53,9 @@ library
Servant.Server.StaticFiles
Servant.Server.UVerb

other-modules:
Servant.Server.TypeErrors

-- deprecated
exposed-modules:
Servant.Utils.StaticFiles
1 change: 1 addition & 0 deletions servant-server/src/Servant/Server.hs
Original file line number Diff line number Diff line change
@@ -126,6 +126,7 @@ import Data.Text
import Network.Wai
(Application)
import Servant.Server.Internal
import Servant.Server.TypeErrors ()
import Servant.Server.UVerb


70 changes: 2 additions & 68 deletions servant-server/src/Servant/Server/Internal.hs
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Char8 as BC8
import qualified Data.ByteString.Lazy as BL
import Data.Constraint (Constraint, Dict(..))
import Data.Constraint (Dict(..))
import Data.Either
(partitionEithers)
import Data.Maybe
@@ -57,7 +57,7 @@ import qualified Data.Text as T
import Data.Typeable
import GHC.Generics
import GHC.TypeLits
(KnownNat, KnownSymbol, TypeError, symbolVal)
(KnownNat, KnownSymbol, symbolVal)
import qualified Network.HTTP.Media as NHM
import Network.HTTP.Types hiding
(Header, ResponseHeaders)
@@ -91,12 +91,9 @@ import Servant.API.ResponseHeaders
import Servant.API.Status
(statusFromNat)
import qualified Servant.Types.SourceT as S
import Servant.API.TypeErrors
import Web.HttpApiData
(FromHttpApiData, parseHeader, parseQueryParam, parseUrlPiece,
parseUrlPieces)
import Data.Kind
(Type)

import Servant.Server.Internal.BasicAuth
import Servant.Server.Internal.Context
@@ -109,8 +106,6 @@ import Servant.Server.Internal.RouteResult
import Servant.Server.Internal.RoutingApplication
import Servant.Server.Internal.ServerError

import GHC.TypeLits
(ErrorMessage (..), TypeError)
import Servant.API.TypeLevel
(AtLeastOneFragment, FragmentUnique)

@@ -819,67 +814,6 @@ instance (HasContextEntry context (NamedContext name subContext), HasServer subA

hoistServerWithContext _ _ nt s = hoistServerWithContext (Proxy :: Proxy subApi) (Proxy :: Proxy subContext) nt s

-------------------------------------------------------------------------------
-- Custom type errors
-------------------------------------------------------------------------------

-- Erroring instance for 'HasServer' when a combinator is not fully applied
instance TypeError (PartialApplication
#if __GLASGOW_HASKELL__ >= 904
@(Type -> [Type] -> Constraint)
#endif
HasServer arr) => HasServer ((arr :: a -> b) :> sub) context
where
type ServerT (arr :> sub) _ = TypeError (PartialApplication (HasServer :: * -> [*] -> Constraint) arr)
route = error "unreachable"
hoistServerWithContext _ _ _ _ = error "unreachable"

-- | This instance prevents from accidentally using '->' instead of ':>'
--
-- >>> serve (Proxy :: Proxy (Capture "foo" Int -> Get '[JSON] Int)) (error "...")
-- ...
-- ...No instance HasServer (a -> b).
-- ...Maybe you have used '->' instead of ':>' between
-- ...Capture' '[] "foo" Int
-- ...and
-- ...Verb 'GET 200 '[JSON] Int
-- ...
--
-- >>> undefined :: Server (Capture "foo" Int -> Get '[JSON] Int)
-- ...
-- ...No instance HasServer (a -> b).
-- ...Maybe you have used '->' instead of ':>' between
-- ...Capture' '[] "foo" Int
-- ...and
-- ...Verb 'GET 200 '[JSON] Int
-- ...
--
instance TypeError (HasServerArrowTypeError a b) => HasServer (a -> b) context
where
type ServerT (a -> b) m = TypeError (HasServerArrowTypeError a b)
route _ _ _ = error "servant-server panic: impossible happened in HasServer (a -> b)"
hoistServerWithContext _ _ _ = id

type HasServerArrowTypeError a b =
'Text "No instance HasServer (a -> b)."
':$$: 'Text "Maybe you have used '->' instead of ':>' between "
':$$: 'ShowType a
':$$: 'Text "and"
':$$: 'ShowType b

-- Erroring instances for 'HasServer' for unknown API combinators

-- XXX: This omits the @context@ parameter, e.g.:
--
-- "There is no instance for HasServer (Bool :> …)". Do we care ?
instance {-# OVERLAPPABLE #-} TypeError (NoInstanceForSub
#if __GLASGOW_HASKELL__ >= 904
@(Type -> [Type] -> Constraint)
#endif
HasServer ty) => HasServer (ty :> sub) context

instance {-# OVERLAPPABLE #-} TypeError (NoInstanceFor (HasServer api context)) => HasServer api context

-- | Ignore @'Fragment'@ in server handlers.
-- See <https://ietf.org/rfc/rfc2616.html#section-15.1.3> for more details.
--
106 changes: 106 additions & 0 deletions servant-server/src/Servant/Server/TypeErrors.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}

#if __GLASGOW_HASKELL__ >= 904
{-# LANGUAGE TypeApplications #-}
#endif

-- | This module contains erroring instances for @Servant.Server.Internal@.
-- They are separated from the bulk of the code, because they raise "missing methods"
-- warnings. These warnings are expected, but ignoring them would lead to missing
-- relevant warnings in @SServant.Server.Internal@. Therefore, we put them in a separate
-- file, and ignore the warnings here.
module Servant.Server.TypeErrors ()
where

import Data.Constraint (Constraint)
import GHC.TypeLits
(TypeError)
import Prelude ()
import Prelude.Compat
import Servant.API
((:>))
import Servant.API.TypeErrors

import Servant.Server.Internal

import GHC.TypeLits
(ErrorMessage (..))

#if __GLASGOW_HASKELL__ >= 904
import Data.Kind (Type)
#endif

-- Erroring instance for 'HasServer' when a combinator is not fully applied
instance TypeError (PartialApplication
#if __GLASGOW_HASKELL__ >= 904
@(Type -> [Type] -> Constraint)
#endif
HasServer arr) => HasServer ((arr :: a -> b) :> sub) context
where
type ServerT (arr :> sub) _ = TypeError (PartialApplication (HasServer :: * -> [*] -> Constraint) arr)
route = error "unreachable"
hoistServerWithContext _ _ _ _ = error "unreachable"

-- | This instance prevents from accidentally using '->' instead of ':>'
--
-- >>> serve (Proxy :: Proxy (Capture "foo" Int -> Get '[JSON] Int)) (error "...")
-- ...
-- ...No instance HasServer (a -> b).
-- ...Maybe you have used '->' instead of ':>' between
-- ...Capture' '[] "foo" Int
-- ...and
-- ...Verb 'GET 200 '[JSON] Int
-- ...
--
-- >>> undefined :: Server (Capture "foo" Int -> Get '[JSON] Int)
-- ...
-- ...No instance HasServer (a -> b).
-- ...Maybe you have used '->' instead of ':>' between
-- ...Capture' '[] "foo" Int
-- ...and
-- ...Verb 'GET 200 '[JSON] Int
-- ...
--
instance TypeError (HasServerArrowTypeError a b) => HasServer (a -> b) context
where
type ServerT (a -> b) m = TypeError (HasServerArrowTypeError a b)
route _ _ _ = error "servant-server panic: impossible happened in HasServer (a -> b)"
hoistServerWithContext _ _ _ = id

type HasServerArrowTypeError a b =
'Text "No instance HasServer (a -> b)."
':$$: 'Text "Maybe you have used '->' instead of ':>' between "
':$$: 'ShowType a
':$$: 'Text "and"
':$$: 'ShowType b

-- Erroring instances for 'HasServer' for unknown API combinators

-- XXX: This omits the @context@ parameter, e.g.:
--
-- "There is no instance for HasServer (Bool :> …)". Do we care ?
instance {-# OVERLAPPABLE #-} TypeError (NoInstanceForSub
#if __GLASGOW_HASKELL__ >= 904
@(Type -> [Type] -> Constraint)
#endif
HasServer ty) => HasServer (ty :> sub) context

instance {-# OVERLAPPABLE #-} TypeError (NoInstanceFor (HasServer api context)) => HasServer api context

-- $setup
-- >>> :set -XDataKinds
-- >>> :set -XTypeOperators
-- >>> import Data.Typeable
-- >>> import Servant.API
-- >>> import Servant.Server
5 changes: 4 additions & 1 deletion servant-server/test/Servant/Server/StreamingSpec.hs
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeOperators #-}

{-# OPTIONS_GHC -fno-warn-deprecations #-}

-- | This module tests whether streaming works from client to server
-- with a server implemented with servant-server.
module Servant.Server.StreamingSpec where
@@ -19,7 +21,8 @@ import Network.Wai
import Network.Wai.Internal
import Prelude ()
import Prelude.Compat
import Servant
import Servant hiding
(respond)
import qualified System.Timeout
import Test.Hspec

Original file line number Diff line number Diff line change
@@ -19,7 +19,8 @@ module Servant.Server.UsingContextSpec.TestCombinators where

import GHC.TypeLits

import Servant
import Servant hiding
(inject)

data ExtractFromContext

1 change: 0 additions & 1 deletion servant-swagger/src/Servant/Swagger/Internal.hs
Original file line number Diff line number Diff line change
@@ -38,7 +38,6 @@ import Network.HTTP.Media (MediaType)
import Servant.API
import Servant.API.Description (FoldDescription,
reflectDescription)
import Servant.API.Generic (ToServantApi, AsApi)
import Servant.API.Modifiers (FoldRequired)

import Servant.Swagger.Internal.TypeLevel.API
4 changes: 4 additions & 0 deletions servant/servant.cabal
Original file line number Diff line number Diff line change
@@ -75,6 +75,10 @@ library
exposed-modules:
Servant.Links

other-modules:
Servant.Links.Internal
Servant.Links.TypeErrors

-- Bundled with GHC: Lower bound to not force re-installs
-- text and mtl are bundled starting with GHC-8.4
--
3 changes: 2 additions & 1 deletion servant/src/Servant/API/TypeErrors.hs
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-}

-- | This module defines the error messages used in type-level errors.
-- Type-level errors can signal non-existing instances, for instance when
-- a combinator is not applied to the correct number of arguments.
@@ -14,7 +16,6 @@ module Servant.API.TypeErrors (
NoInstanceForSub,
) where

import Data.Kind
import GHC.TypeLits

-- | No instance exists for @tycls (expr :> ...)@ because
677 changes: 8 additions & 669 deletions servant/src/Servant/Links.hs

Large diffs are not rendered by default.

647 changes: 647 additions & 0 deletions servant/src/Servant/Links/Internal.hs

Large diffs are not rendered by default.

56 changes: 56 additions & 0 deletions servant/src/Servant/Links/TypeErrors.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}

#if __GLASGOW_HASKELL__ >= 904
{-# LANGUAGE TypeApplications #-}
#endif

-- | This module contains erroring instances for @Servant.Links.Internal@.
-- They are separated from the bulk of the code, because they raise "missing methods"
-- warnings. These warnings are expected, but ignoring them would lead to missing
-- relevant warnings in @Servant.Links.Internal@. Therefore, we put them in a separate
-- file, and ignore the warnings here.
module Servant.Links.TypeErrors ()
where

import Data.Constraint
import GHC.TypeLits
(TypeError)
import Prelude ()
import Prelude.Compat

import Servant.API.Sub
(type (:>))
import Servant.API.TypeErrors
import Servant.Links.Internal

#if __GLASGOW_HASKELL__ >= 904
import Data.Kind (Type)
#endif

-- Erroring instance for 'HasLink' when a combinator is not fully applied
instance TypeError (PartialApplication
#if __GLASGOW_HASKELL__ >= 904
@(Type -> Constraint)
#endif
HasLink arr) => HasLink ((arr :: a -> b) :> sub)
where
type MkLink (arr :> sub) _ = TypeError (PartialApplication (HasLink :: * -> Constraint) arr)
toLink = error "unreachable"

-- Erroring instances for 'HasLink' for unknown API combinators
instance {-# OVERLAPPABLE #-} TypeError (NoInstanceForSub
#if __GLASGOW_HASKELL__ >= 904
@(Type -> Constraint)
#endif
HasLink ty) => HasLink (ty :> sub)

instance {-# OVERLAPPABLE #-} TypeError (NoInstanceFor (HasLink api)) => HasLink api