@@ -56,7 +56,7 @@ import qualified Data.Text as T
5656import Data.Typeable
5757import GHC.Generics
5858import GHC.TypeLits
59− (KnownNat, KnownSymbol, natVal, symbolVal)
59+ (KnownNat, KnownSymbol, TypeError, natVal, symbolVal)
6060import qualified Network.HTTP.Media as NHM
6161import Network.HTTP.Types hiding
6262 (Header, ResponseHeaders)
@@ -88,6 +88,7 @@ import Servant.API.Modifiers
8888import Servant.API.ResponseHeaders
8989 (GetHeaders, Headers, getHeaders, getResponse)
9090import qualified Servant.Types.SourceT as S
91+import Servant.API.TypeErrors
9192import Web.HttpApiData
9293 (FromHttpApiData, parseHeader, parseQueryParam, parseUrlPiece,
9394 parseUrlPieces)
@@ -812,38 +813,15 @@ instance (HasContextEntry context (NamedContext name subContext), HasServer subA
812813 hoistServerWithContext _ _ nt s = hoistServerWithContext (Proxy :: Proxy subApi) (Proxy :: Proxy subContext) nt s
813814
814815-------------------------------------------------------------------------------
815−-- TypeError helpers
816+-- Custom type errors
816817-------------------------------------------------------------------------------
817818
818−-- | This instance catches mistakes when there are non-saturated
819−-- type applications on LHS of ':>'.
820−--
821−-- >>> serve (Proxy :: Proxy (Capture "foo" :> Get '[JSON] Int)) (error "...")
822−-- ...
823−-- ...Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'.
824−-- ...Maybe you haven't applied enough arguments to
825−-- ...Capture' '[] "foo"
826−-- ...
827−--
828−-- >>> undefined :: Server (Capture "foo" :> Get '[JSON] Int)
829−-- ...
830−-- ...Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'.
831−-- ...Maybe you haven't applied enough arguments to
832−-- ...Capture' '[] "foo"
833−-- ...
834−--
835−instance TypeError (HasServerArrowKindError arr) => HasServer ((arr :: k -> l) :> api) context
819+-- Erroring instance for 'HasServer' when a combinator is not fully applied
820+instance TypeError (PartialApplication HasServer arr) => HasServer ((arr :: a -> b) :> sub) context
836821 where
837− type ServerT (arr :> api) m = TypeError (HasServerArrowKindError arr)
838− -- it doesn't really matter what sub route we peak
839− route _ _ _ = error "servant-server panic: impossible happened in HasServer (arr :> api)"
840− hoistServerWithContext _ _ _ = id
841−
842−-- Cannot have TypeError here, otherwise use of this symbol will error :)
843−type HasServerArrowKindError arr =
844− 'Text "Expected something of kind Symbol or *, got: k -> l on the LHS of ':>'."
845− ':$$: 'Text "Maybe you haven't applied enough arguments to"
846− ':$$: 'ShowType arr
822+ type ServerT (arr :> sub) _ = TypeError (PartialApplication HasServer arr)
823+ route = error "unreachable"
824+ hoistServerWithContext _ _ _ _ = error "unreachable"
847825
848826-- | This instance prevents from accidentally using '->' instead of ':>'
849827--
@@ -878,6 +856,15 @@ type HasServerArrowTypeError a b =
878856 ':$$: 'Text "and"
879857 ':$$: 'ShowType b
880858
859+-- Erroring instances for 'HasServer' for unknown API combinators
860+
861+-- XXX: This omits the @context@ parameter, e.g.:
862+--
863+-- "There is no instance for HasServer (Bool :> …)". Do we care ?
864+instance {-# OVERLAPPABLE #-} TypeError (NoInstanceForSub HasServer ty) => HasServer (ty :> sub) context
865+
866+instance {-# OVERLAPPABLE #-} TypeError (NoInstanceFor (HasServer api context)) => HasServer api context
867+
881868-- | Ignore @'Fragment'@ in server handlers.
882869-- See <https://ietf.org/rfc/rfc2616.html#section-15.1.3> for more details.
883870--