@@ -41,7 +41,7 @@ import qualified Data.ByteString as B
4141import qualified Data.ByteString.Builder as BB
4242import qualified Data.ByteString.Char8 as BC8
4343import qualified Data.ByteString.Lazy as BL
44−import Data.Constraint (Constraint, Dict(..))
44+import Data.Constraint (Dict(..))
4545import Data.Either
4646 (partitionEithers)
4747import Data.Maybe
@@ -56,7 +56,7 @@ import qualified Data.Text as T
5656import Data.Typeable
5757import GHC.Generics
5858import GHC.TypeLits
59− (KnownNat, KnownSymbol, TypeError, symbolVal)
59+ (KnownNat, KnownSymbol, symbolVal)
6060import qualified Network.HTTP.Media as NHM
6161import Network.HTTP.Types hiding
6262 (Header, ResponseHeaders)
@@ -90,7 +90,6 @@ import Servant.API.ResponseHeaders
9090import Servant.API.Status
9191 (statusFromNat)
9292import qualified Servant.Types.SourceT as S
93−import Servant.API.TypeErrors
9493import Web.HttpApiData
9594 (FromHttpApiData, parseHeader, parseQueryParam, parseUrlPiece,
9695 parseUrlPieces)
@@ -173,7 +172,7 @@ instance (HasServer a context, HasServer b context) => HasServer (a :<|> b) cont
173172-- > server = getBook
174173-- > where getBook :: Text -> Handler Book
175174-- > getBook isbn = ...
176−instance (KnownSymbol capture, FromHttpApiData a, Typeable a
175+instance (KnownSymbol capture, FromHttpApiData a
177176 , HasServer api context, SBoolI (FoldLenient mods)
178177 , HasContextEntry (MkContextWithErrorFormatter context) ErrorFormatters
179178 )
@@ -185,7 +184,7 @@ instance (KnownSymbol capture, FromHttpApiData a, Typeable a
185184 hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s
186185
187186 route Proxy context d =
188− CaptureRouter [hint] $
187+ CaptureRouter $
189188 route (Proxy :: Proxy api)
190189 context
191190 (addCapture d $ \ txt -> withRequest $ \ request ->
@@ -197,7 +196,6 @@ instance (KnownSymbol capture, FromHttpApiData a, Typeable a
197196 where
198197 rep = typeRep (Proxy :: Proxy Capture')
199198 formatError = urlParseErrorFormatter $ getContextEntry (mkContextWithErrorFormatter context)
200− hint = CaptureHint (T.pack $ symbolVal $ Proxy @capture) (typeRep (Proxy :: Proxy a))
201199
202200-- | If you use 'CaptureAll' in one of the endpoints for your API,
203201-- this automatically requires your server-side handler to be a
@@ -216,7 +214,7 @@ instance (KnownSymbol capture, FromHttpApiData a, Typeable a
216214-- > server = getSourceFile
217215-- > where getSourceFile :: [Text] -> Handler Book
218216-- > getSourceFile pathSegments = ...
219−instance (KnownSymbol capture, FromHttpApiData a, Typeable a
217+instance (KnownSymbol capture, FromHttpApiData a
220218 , HasServer api context
221219 , HasContextEntry (MkContextWithErrorFormatter context) ErrorFormatters
222220 )
@@ -228,7 +226,7 @@ instance (KnownSymbol capture, FromHttpApiData a, Typeable a
228226 hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s
229227
230228 route Proxy context d =
231− CaptureAllRouter [hint] $
229+ CaptureAllRouter $
232230 route (Proxy :: Proxy api)
233231 context
234232 (addCapture d $ \ txts -> withRequest $ \ request ->
@@ -239,7 +237,6 @@ instance (KnownSymbol capture, FromHttpApiData a, Typeable a
239237 where
240238 rep = typeRep (Proxy :: Proxy CaptureAll)
241239 formatError = urlParseErrorFormatter $ getContextEntry (mkContextWithErrorFormatter context)
242− hint = CaptureHint (T.pack $ symbolVal $ Proxy @capture) (typeRep (Proxy :: Proxy [a]))
243240
244241allowedMethodHead :: Method -> Request -> Bool
245242allowedMethodHead method request = method == methodGet && requestMethod request == methodHead
@@ -817,15 +814,38 @@ instance (HasContextEntry context (NamedContext name subContext), HasServer subA
817814 hoistServerWithContext _ _ nt s = hoistServerWithContext (Proxy :: Proxy subApi) (Proxy :: Proxy subContext) nt s
818815
819816-------------------------------------------------------------------------------
820−-- Custom type errors
817+-- TypeError helpers
821818-------------------------------------------------------------------------------
822819
823−-- Erroring instance for 'HasServer' when a combinator is not fully applied
824−instance TypeError (PartialApplication HasServer arr) => HasServer ((arr :: a -> b) :> sub) context
820+-- | This instance catches mistakes when there are non-saturated
821+-- type applications on LHS of ':>'.
822+--
823+-- >>> serve (Proxy :: Proxy (Capture "foo" :> Get '[JSON] Int)) (error "...")
824+-- ...
825+-- ...Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'.
826+-- ...Maybe you haven't applied enough arguments to
827+-- ...Capture' '[] "foo"
828+-- ...
829+--
830+-- >>> undefined :: Server (Capture "foo" :> Get '[JSON] Int)
831+-- ...
832+-- ...Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'.
833+-- ...Maybe you haven't applied enough arguments to
834+-- ...Capture' '[] "foo"
835+-- ...
836+--
837+instance TypeError (HasServerArrowKindError arr) => HasServer ((arr :: k -> l) :> api) context
825838 where
826− type ServerT (arr :> sub) _ = TypeError (PartialApplication (HasServer :: * -> [*] -> Constraint) arr)
827− route = error "unreachable"
828− hoistServerWithContext _ _ _ _ = error "unreachable"
839+ type ServerT (arr :> api) m = TypeError (HasServerArrowKindError arr)
840+ -- it doesn't really matter what sub route we peak
841+ route _ _ _ = error "servant-server panic: impossible happened in HasServer (arr :> api)"
842+ hoistServerWithContext _ _ _ = id
843+
844+-- Cannot have TypeError here, otherwise use of this symbol will error :)
845+type HasServerArrowKindError arr =
846+ 'Text "Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'."
847+ ':$$: 'Text "Maybe you haven't applied enough arguments to"
848+ ':$$: 'ShowType arr
829849
830850-- | This instance prevents from accidentally using '->' instead of ':>'
831851--
@@ -860,15 +880,6 @@ type HasServerArrowTypeError a b =
860880 ':$$: 'Text "and"
861881 ':$$: 'ShowType b
862882
863−-- Erroring instances for 'HasServer' for unknown API combinators
864−
865−-- XXX: This omits the @context@ parameter, e.g.:
866−--
867−-- "There is no instance for HasServer (Bool :> …)". Do we care ?
868−instance {-# OVERLAPPABLE #-} TypeError (NoInstanceForSub HasServer ty) => HasServer (ty :> sub) context
869−
870−instance {-# OVERLAPPABLE #-} TypeError (NoInstanceFor (HasServer api context)) => HasServer api context
871−
872883-- | Ignore @'Fragment'@ in server handlers.
873884-- See <https://ietf.org/rfc/rfc2616.html#section-15.1.3> for more details.
874885--