diff --git a/derive/src/endpoint.rs b/derive/src/endpoint.rs index a2523efda9..b6a6b1e46c 100644 --- a/derive/src/endpoint.rs +++ b/derive/src/endpoint.rs @@ -531,14 +531,16 @@ fn expand_endpoint_type( ) }); let output_struct = schema.map(|schema_fn| { - let output_struct_ident = output_struct_ident.as_ref().unwrap_or_else(|| unreachable!()); + let output_struct_ident = output_struct_ident + .as_ref() + .unwrap_or_else(|| unreachable!()); let status_codes_fn = status_codes.unwrap_or_else(|| unreachable!()); let schema_call = quote_spanned! { schema_fn.span() => - let schema: ::gotham_restful::private::OpenapiSchema = #schema_fn(code); + let schema = ::gotham_restful::private::CustomSchema::schema(#schema_fn, code); }; let status_codes_call = quote_spanned! { status_codes_fn.span() => - let status_codes: ::std::vec::Vec<::gotham_restful::gotham::hyper::StatusCode> = #status_codes_fn(); + let status_codes = ::gotham_restful::private::CustomStatusCodes::status_codes(#status_codes_fn); }; quote! { @@ -563,7 +565,9 @@ fn expand_endpoint_type( ::gotham_restful::IntoResponse::into_response(self.0) } - fn accepted_types() -> ::core::option::Option<::std::vec::Vec<::gotham_restful::gotham::mime::Mime>> { + fn accepted_types() -> ::core::option::Option< + ::std::vec::Vec<::gotham_restful::gotham::mime::Mime>> + { <#output_ty as ::gotham_restful::IntoResponse>::accepted_types() } } diff --git a/src/lib.rs b/src/lib.rs index ce2bfd72f9..9a13df989a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -496,14 +496,57 @@ pub mod private { pub use openapi_type::{OpenapiSchema, OpenapiType, Visitor}; pub use serde_json; + #[cfg(feature = "openapi")] + use gotham::hyper::StatusCode; + #[cfg(feature = "auth")] use gotham::state::{FromState, State}; + /// This method is used by the endpoint macro to generate a good error message + /// when the used AuthData type does not implement Clone. + #[cfg(feature = "auth")] + #[inline] pub fn clone_from_state(state: &State) -> T where T: FromState + Clone { T::borrow_from(state).clone() } + + /// This trait is used by the endpoint macro to generate a good error message + /// when the schema function has the wrong signature. + #[cfg(feature = "openapi")] + pub trait CustomSchema { + fn schema(self, code: StatusCode) -> OpenapiSchema; + } + + #[cfg(feature = "openapi")] + impl CustomSchema for F + where + F: FnOnce(StatusCode) -> OpenapiSchema + { + #[inline] + fn schema(self, code: StatusCode) -> OpenapiSchema { + self(code) + } + } + + /// This trait is used by the endpoint macro to generate a good error message + /// when the status_codes function has the wrong signature. + #[cfg(feature = "openapi")] + pub trait CustomStatusCodes { + fn status_codes(self) -> Vec; + } + + #[cfg(feature = "openapi")] + impl CustomStatusCodes for F + where + F: FnOnce() -> Vec + { + #[inline] + fn status_codes(self) -> Vec { + self() + } + } } #[cfg(feature = "auth")] diff --git a/tests/ui/endpoint/dynamic_schema_wrong_type.stderr b/tests/ui/endpoint/dynamic_schema_wrong_type.stderr index a404777b8e..1cee4a4d94 100644 --- a/tests/ui/endpoint/dynamic_schema_wrong_type.stderr +++ b/tests/ui/endpoint/dynamic_schema_wrong_type.stderr @@ -1,39 +1,22 @@ -error[E0308]: mismatched types +error[E0631]: type mismatch in function arguments --> tests/ui/endpoint/dynamic_schema_wrong_type.rs:16:21 | -16 | #[read_all(schema = "schema", status_codes = "status_codes")] - | ^^^^^^^^ - | | - | expected `u16`, found struct `StatusCode` - | arguments to this function are incorrect - | -note: function defined here - --> tests/ui/endpoint/dynamic_schema_wrong_type.rs:8:4 - | 8 | fn schema(_: u16) -> String { - | ^^^^^^ ------ -help: call `Into::into` on this expression to convert `StatusCode` into `u16` - | -16 | #[read_all(schema = "schema".into(), status_codes = "status_codes")] - | +++++++ - -error[E0308]: mismatched types - --> tests/ui/endpoint/dynamic_schema_wrong_type.rs:16:21 - | + | --------------------------- found signature defined here +... 16 | #[read_all(schema = "schema", status_codes = "status_codes")] - | ^^^^^^^^ - | | - | expected struct `OpenapiSchema`, found struct `std::string::String` - | expected due to this + | ^^^^^^^^ expected due to this + | + = note: expected function signature `fn(StatusCode) -> _` + found function signature `fn(u16) -> _` + = note: required for `fn(u16) -> std::string::String {schema}` to implement `CustomSchema` -error[E0308]: mismatched types +error[E0271]: expected `fn() -> Vec {status_codes}` to be a fn item that returns `Vec`, but it returns `Vec` --> tests/ui/endpoint/dynamic_schema_wrong_type.rs:16:46 | 16 | #[read_all(schema = "schema", status_codes = "status_codes")] - | ^^^^^^^^^^^^^^ - | | - | expected struct `StatusCode`, found `u16` - | expected due to this + | ^^^^^^^^^^^^^^ expected struct `StatusCode`, found `u16` | = note: expected struct `Vec` found struct `Vec` + = note: required for `fn() -> Vec {status_codes}` to implement `CustomStatusCodes`