diff --git a/src/extract.rs b/src/extract.rs index f74a0a54e..de1cdde0c 100644 --- a/src/extract.rs +++ b/src/extract.rs @@ -290,16 +290,6 @@ impl FromRequest for Method { } } -#[doc(hidden)] -impl FromRequest for () { - type Error = Infallible; - type Future = Ready>; - - fn from_request(_: &HttpRequest, _: &mut Payload) -> Self::Future { - ok(()) - } -} - #[doc(hidden)] #[allow(non_snake_case)] mod tuple_from_req { @@ -388,6 +378,15 @@ mod tuple_from_req { } } + impl FromRequest for () { + type Error = Infallible; + type Future = Ready>; + + fn from_request(_: &HttpRequest, _: &mut Payload) -> Self::Future { + ok(()) + } + } + tuple_from_req! { TupleFromRequest1; A } tuple_from_req! { TupleFromRequest2; A, B } tuple_from_req! { TupleFromRequest3; A, B, C } @@ -398,6 +397,8 @@ mod tuple_from_req { tuple_from_req! { TupleFromRequest8; A, B, C, D, E, F, G, H } tuple_from_req! { TupleFromRequest9; A, B, C, D, E, F, G, H, I } tuple_from_req! { TupleFromRequest10; A, B, C, D, E, F, G, H, I, J } + tuple_from_req! { TupleFromRequest11; A, B, C, D, E, F, G, H, I, J, K } + tuple_from_req! { TupleFromRequest12; A, B, C, D, E, F, G, H, I, J, K, L } } #[cfg(test)] diff --git a/src/handler.rs b/src/handler.rs index d458e22e1..841d11a16 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -11,18 +11,17 @@ use crate::{ /// /// # What Is A Request Handler /// A request handler has three requirements: -/// 1. It is an async function (or a function/closure that returns an appropriate future); -/// 1. The function accepts zero or more parameters that implement [`FromRequest`]; -/// 1. The async function (or future) resolves to a type that can be converted into an +/// 1. It is an async function (or a function/closure that returns an appropriate future) +/// and has no more than 12 paramters; +/// 2. The function parameters implement [`FromRequest`]; +/// 3. The async function (or future) resolves to a type that can be converted into an /// [`HttpResponse`] (i.e., it implements the [`Responder`] trait). /// /// # Compiler Errors /// If you get the error `the trait Handler<_> is not implemented`, then your handler does not -/// fulfill one or more of the above requirements. -/// -/// Unfortunately we cannot provide a better compile error message (while keeping the trait's -/// flexibility) unless a stable alternative to [`#[rustc_on_unimplemented]`][on_unimpl] is added -/// to Rust. +/// fulfill the _first_ of the above requirements. +/// Missing other requirements manifest as errors on implementing [`FromRequest`] and [`Responder`] +/// , respectively. /// /// # How Do Handlers Receive Variable Numbers Of Arguments /// Rest assured there is no macro magic here; it's just traits. @@ -76,7 +75,6 @@ use crate::{ /// /// [arity]: https://en.wikipedia.org/wiki/Arity /// [`from_request`]: FromRequest::from_request -/// [on_unimpl]: https://github.com/rust-lang/rust/issues/29628 pub trait Handler: Clone + 'static { type Output; type Future: Future; @@ -148,3 +146,33 @@ factory_tuple! { A B C D E F G H I } factory_tuple! { A B C D E F G H I J } factory_tuple! { A B C D E F G H I J K } factory_tuple! { A B C D E F G H I J K L } + +#[cfg(test)] +mod tests { + use super::*; + + fn assert_impl_handler(_: impl Handler) {} + + #[test] + fn arg_number() { + async fn handler_min() {} + async fn handler_max( + _01: (), + _02: (), + _03: (), + _04: (), + _05: (), + _06: (), + _07: (), + _08: (), + _09: (), + _10: (), + _11: (), + _12: (), + ) { + } + + assert_impl_handler(handler_min); + assert_impl_handler(handler_max); + } +}