diff --git a/axum-extra/src/routing/mod.rs b/axum-extra/src/routing/mod.rs index d64e1ff986..ad348292a0 100644 --- a/axum-extra/src/routing/mod.rs +++ b/axum-extra/src/routing/mod.rs @@ -24,7 +24,7 @@ pub use self::resource::Resource; pub use axum_macros::TypedPath; #[cfg(feature = "typed-routing")] -pub use self::typed::{FirstElementIs, TypedPath}; +pub use self::typed::{SecondElementIs, TypedPath}; #[cfg(feature = "spa")] pub use self::spa::SpaRouter; @@ -41,7 +41,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_get(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `DELETE` route to the router. @@ -54,7 +54,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_delete(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `HEAD` route to the router. @@ -67,7 +67,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_head(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `OPTIONS` route to the router. @@ -80,7 +80,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_options(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `PATCH` route to the router. @@ -93,7 +93,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_patch(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `POST` route to the router. @@ -106,7 +106,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_post(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `PUT` route to the router. @@ -119,7 +119,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_put(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add a typed `TRACE` route to the router. @@ -132,7 +132,7 @@ pub trait RouterExt: sealed::Sealed { fn typed_trace(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath; /// Add another route to the router with an additional "trailing slash redirect" route. @@ -184,7 +184,7 @@ where fn typed_get(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::get(handler)) @@ -194,7 +194,7 @@ where fn typed_delete(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::delete(handler)) @@ -204,7 +204,7 @@ where fn typed_head(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::head(handler)) @@ -214,7 +214,7 @@ where fn typed_options(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::options(handler)) @@ -224,7 +224,7 @@ where fn typed_patch(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::patch(handler)) @@ -234,7 +234,7 @@ where fn typed_post(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::post(handler)) @@ -244,7 +244,7 @@ where fn typed_put(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::put(handler)) @@ -254,7 +254,7 @@ where fn typed_trace(self, handler: H) -> Self where H: Handler, - T: FirstElementIs

+ 'static, + T: SecondElementIs

+ 'static, P: TypedPath, { self.route(P::PATH, axum::routing::trace(handler)) diff --git a/axum-extra/src/routing/typed.rs b/axum-extra/src/routing/typed.rs index 159472a063..aeb9936c0b 100644 --- a/axum-extra/src/routing/typed.rs +++ b/axum-extra/src/routing/typed.rs @@ -231,10 +231,10 @@ pub trait TypedPath: std::fmt::Display { } } -/// Utility trait used with [`RouterExt`] to ensure the first element of a tuple type is a +/// Utility trait used with [`RouterExt`] to ensure the second element of a tuple type is a /// given type. /// -/// If you see it in type errors its most likely because the first argument to your handler doesn't +/// If you see it in type errors its most likely because the second argument to your handler doesn't /// implement [`TypedPath`]. /// /// You normally shouldn't have to use this trait directly. @@ -242,56 +242,56 @@ pub trait TypedPath: std::fmt::Display { /// It is sealed such that it cannot be implemented outside this crate. /// /// [`RouterExt`]: super::RouterExt -pub trait FirstElementIs

: Sealed {} +pub trait SecondElementIs

: Sealed {} -macro_rules! impl_first_element_is { +macro_rules! impl_second_element_is { ( $($ty:ident),* $(,)? ) => { - impl FirstElementIs

for (P, $($ty,)*) + impl SecondElementIs

for (M, P, $($ty,)*) where P: TypedPath {} - impl Sealed for (P, $($ty,)*) + impl Sealed for (M, P, $($ty,)*) where P: TypedPath {} - impl FirstElementIs

for (Option

, $($ty,)*) + impl SecondElementIs

for (M, Option

, $($ty,)*) where P: TypedPath {} - impl Sealed for (Option

, $($ty,)*) + impl Sealed for (M, Option

, $($ty,)*) where P: TypedPath {} - impl FirstElementIs

for (Result, $($ty,)*) + impl SecondElementIs

for (M, Result, $($ty,)*) where P: TypedPath {} - impl Sealed for (Result, $($ty,)*) + impl Sealed for (M, Result, $($ty,)*) where P: TypedPath {} }; } -impl_first_element_is!(); -impl_first_element_is!(T1); -impl_first_element_is!(T1, T2); -impl_first_element_is!(T1, T2, T3); -impl_first_element_is!(T1, T2, T3, T4); -impl_first_element_is!(T1, T2, T3, T4, T5); -impl_first_element_is!(T1, T2, T3, T4, T5, T6); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15); -impl_first_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16); +impl_second_element_is!(); +impl_second_element_is!(T1); +impl_second_element_is!(T1, T2); +impl_second_element_is!(T1, T2, T3); +impl_second_element_is!(T1, T2, T3, T4); +impl_second_element_is!(T1, T2, T3, T4, T5); +impl_second_element_is!(T1, T2, T3, T4, T5, T6); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15); +impl_second_element_is!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16); diff --git a/axum-macros/src/debug_handler.rs b/axum-macros/src/debug_handler.rs index 0fe8ad6af4..7c261b500e 100644 --- a/axum-macros/src/debug_handler.rs +++ b/axum-macros/src/debug_handler.rs @@ -1,14 +1,11 @@ -use std::collections::HashSet; - use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned}; +use std::collections::HashSet; use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, Token, Type}; pub(crate) fn expand(mut attr: Attrs, item_fn: ItemFn) -> TokenStream { let check_extractor_count = check_extractor_count(&item_fn); - let check_request_last_extractor = check_request_last_extractor(&item_fn); let check_path_extractor = check_path_extractor(&item_fn); - let check_multiple_body_extractors = check_multiple_body_extractors(&item_fn); let check_output_impls_into_response = check_output_impls_into_response(&item_fn); // If the function is generic, we can't reliably check its inputs or whether the future it @@ -39,9 +36,7 @@ pub(crate) fn expand(mut attr: Attrs, item_fn: ItemFn) -> TokenStream { quote! { #item_fn #check_extractor_count - #check_request_last_extractor #check_path_extractor - #check_multiple_body_extractors #check_output_impls_into_response #check_inputs_and_future_send } @@ -135,22 +130,6 @@ fn extractor_idents(item_fn: &ItemFn) -> impl Iterator Option { - let request_extractor_ident = - extractor_idents(item_fn).find(|(_, _, ident)| *ident == "Request"); - - if let Some((idx, fn_arg, _)) = request_extractor_ident { - if idx != item_fn.sig.inputs.len() - 1 { - return Some( - syn::Error::new_spanned(fn_arg, "`Request` extractor should always be last") - .to_compile_error(), - ); - } - } - - None -} - fn check_path_extractor(item_fn: &ItemFn) -> TokenStream { let path_extractors = extractor_idents(item_fn) .filter(|(_, _, ident)| *ident == "Path") @@ -174,30 +153,14 @@ fn check_path_extractor(item_fn: &ItemFn) -> TokenStream { } } -fn check_multiple_body_extractors(item_fn: &ItemFn) -> TokenStream { - let body_extractors = extractor_idents(item_fn) - .filter(|(_, _, ident)| { - *ident == "String" - || *ident == "Bytes" - || *ident == "Json" - || *ident == "RawBody" - || *ident == "BodyStream" - || *ident == "Multipart" - || *ident == "Request" - }) - .collect::>(); - - if body_extractors.len() > 1 { - body_extractors - .into_iter() - .map(|(_, arg, _)| { - syn::Error::new_spanned(arg, "Only one body extractor can be applied") - .to_compile_error() - }) - .collect() +fn is_self_pat_type(typed: &syn::PatType) -> bool { + let ident = if let syn::Pat::Ident(ident) = &*typed.pat { + &ident.ident } else { - quote! {} - } + return false; + }; + + ident == "self" } fn check_inputs_impls_from_request( @@ -205,6 +168,11 @@ fn check_inputs_impls_from_request( body_ty: &Type, state_ty: Type, ) -> TokenStream { + let takes_self = item_fn.sig.inputs.first().map_or(false, |arg| match arg { + FnArg::Receiver(_) => true, + FnArg::Typed(typed) => is_self_pat_type(typed), + }); + item_fn .sig .inputs @@ -227,21 +195,53 @@ fn check_inputs_impls_from_request( FnArg::Typed(typed) => { let ty = &typed.ty; let span = ty.span(); - (span, ty.clone()) + + if is_self_pat_type(typed) { + (span, syn::parse_quote!(Self)) + } else { + (span, ty.clone()) + } } }; - let name = format_ident!( - "__axum_macros_check_{}_{}_from_request", + let check_fn = format_ident!( + "__axum_macros_check_{}_{}_from_request_check", item_fn.sig.ident, - idx + idx, + span = span, ); + + let call_check_fn = format_ident!( + "__axum_macros_check_{}_{}_from_request_call_check", + item_fn.sig.ident, + idx, + span = span, + ); + + let call_check_fn_body = if takes_self { + quote_spanned! {span=> + Self::#check_fn(); + } + } else { + quote_spanned! {span=> + #check_fn(); + } + }; + quote_spanned! {span=> #[allow(warnings)] - fn #name() + fn #check_fn() where - #ty: ::axum::extract::FromRequest<#state_ty, #body_ty> + Send, + #ty: ::axum::extract::FromRequest<#state_ty, #body_ty, M> + Send, {} + + // we have to call the function to actually trigger a compile error + // since the function is generic, just defining it is not enough + #[allow(warnings)] + fn #call_check_fn() + { + #call_check_fn_body + } } }) .collect::() @@ -380,11 +380,11 @@ fn check_future_send(item_fn: &ItemFn) -> TokenStream { } fn self_receiver(item_fn: &ItemFn) -> Option { - let takes_self = item_fn - .sig - .inputs - .iter() - .any(|arg| matches!(arg, syn::FnArg::Receiver(_))); + let takes_self = item_fn.sig.inputs.iter().any(|arg| match arg { + FnArg::Receiver(_) => true, + FnArg::Typed(typed) => is_self_pat_type(typed), + }); + if takes_self { return Some(quote! { Self:: }); } diff --git a/axum-macros/src/typed_path.rs b/axum-macros/src/typed_path.rs index 9df4702881..efbf733cc0 100644 --- a/axum-macros/src/typed_path.rs +++ b/axum-macros/src/typed_path.rs @@ -127,15 +127,17 @@ fn expand_named_fields( let from_request_impl = quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident + impl ::axum::extract::FromRequestParts for #ident where - B: Send, S: Send + Sync, { type Rejection = #rejection_assoc_type; - async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { - ::axum::extract::Path::from_request(req) + async fn from_request_parts( + parts: &mut ::axum::http::request::Parts, + state: &S, + ) -> ::std::result::Result { + ::axum::extract::Path::from_request_parts(parts, state) .await .map(|path| path.0) #map_err_rejection @@ -230,15 +232,17 @@ fn expand_unnamed_fields( let from_request_impl = quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident + impl ::axum::extract::FromRequestParts for #ident where - B: Send, S: Send + Sync, { type Rejection = #rejection_assoc_type; - async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { - ::axum::extract::Path::from_request(req) + async fn from_request_parts( + parts: &mut ::axum::http::request::Parts, + state: &S, + ) -> ::std::result::Result { + ::axum::extract::Path::from_request_parts(parts, state) .await .map(|path| path.0) #map_err_rejection @@ -312,15 +316,17 @@ fn expand_unit_fields( let from_request_impl = quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident + impl ::axum::extract::FromRequestParts for #ident where - B: Send, S: Send + Sync, { type Rejection = #rejection_assoc_type; - async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { - if req.uri().path() == ::PATH { + async fn from_request_parts( + parts: &mut ::axum::http::request::Parts, + _state: &S, + ) -> ::std::result::Result { + if parts.uri.path() == ::PATH { Ok(Self) } else { #create_rejection @@ -390,7 +396,7 @@ enum Segment { fn path_rejection() -> TokenStream { quote! { - <::axum::extract::Path as ::axum::extract::FromRequest>::Rejection + <::axum::extract::Path as ::axum::extract::FromRequestParts>::Rejection } } diff --git a/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr index 265258419e..e7a69e1300 100644 --- a/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr +++ b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr @@ -1,17 +1,22 @@ -error[E0277]: the trait bound `bool: FromRequest<(), Body>` is not satisfied +error[E0277]: the trait bound `bool: FromRequestParts<()>` is not satisfied --> tests/debug_handler/fail/argument_not_extractor.rs:4:23 | 4 | async fn handler(foo: bool) {} - | ^^^^ the trait `FromRequest<(), Body>` is not implemented for `bool` + | ^^^^ the trait `FromRequestParts<()>` is not implemented for `bool` | - = help: the following other types implement trait `FromRequest`: - <() as FromRequest> - <(T1, T2) as FromRequest> - <(T1, T2, T3) as FromRequest> - <(T1, T2, T3, T4) as FromRequest> - <(T1, T2, T3, T4, T5) as FromRequest> - <(T1, T2, T3, T4, T5, T6) as FromRequest> - <(T1, T2, T3, T4, T5, T6, T7) as FromRequest> - <(T1, T2, T3, T4, T5, T6, T7, T8) as FromRequest> - and 34 others - = help: see issue #48214 + = help: the following other types implement trait `FromRequestParts`: + as FromRequestParts> + as FromRequestParts> + as FromRequestParts> + > + > + > + as FromRequestParts> + > + and 9 others + = note: required because of the requirements on the impl of `FromRequest<(), Body, axum_core::extract::private::Mut>` for `bool` +note: required by a bound in `__axum_macros_check_handler_0_from_request_check` + --> tests/debug_handler/fail/argument_not_extractor.rs:4:23 + | +4 | async fn handler(foo: bool) {} + | ^^^^ required by this bound in `__axum_macros_check_handler_0_from_request_check` diff --git a/axum-macros/tests/debug_handler/fail/extract_self_mut.rs b/axum-macros/tests/debug_handler/fail/extract_self_mut.rs index 168a1c8177..d20426e22f 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_mut.rs +++ b/axum-macros/tests/debug_handler/fail/extract_self_mut.rs @@ -1,6 +1,7 @@ use axum::{ async_trait, - extract::{FromRequest, RequestParts}, + extract::FromRequest, + http::Request, }; use axum_macros::debug_handler; @@ -9,12 +10,12 @@ struct A; #[async_trait] impl FromRequest for A where - B: Send, + B: Send + 'static, S: Send + Sync, { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: Request, _state: &S) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr b/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr index 3d80dffbca..1e1a9ec384 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr +++ b/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr @@ -1,5 +1,5 @@ error: Handlers must only take owned values - --> tests/debug_handler/fail/extract_self_mut.rs:24:22 + --> tests/debug_handler/fail/extract_self_mut.rs:25:22 | -24 | async fn handler(&mut self) {} +25 | async fn handler(&mut self) {} | ^^^^^^^^^ diff --git a/axum-macros/tests/debug_handler/fail/extract_self_ref.rs b/axum-macros/tests/debug_handler/fail/extract_self_ref.rs index 4090265cd6..77940e2996 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_ref.rs +++ b/axum-macros/tests/debug_handler/fail/extract_self_ref.rs @@ -1,6 +1,7 @@ use axum::{ async_trait, - extract::{FromRequest, RequestParts}, + extract::FromRequest, + http::Request, }; use axum_macros::debug_handler; @@ -9,12 +10,12 @@ struct A; #[async_trait] impl FromRequest for A where - B: Send, + B: Send + 'static, S: Send + Sync, { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: Request, _state: &S) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr b/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr index 82d9a89ff5..79f9d190f5 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr +++ b/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr @@ -1,5 +1,5 @@ error: Handlers must only take owned values - --> tests/debug_handler/fail/extract_self_ref.rs:24:22 + --> tests/debug_handler/fail/extract_self_ref.rs:25:22 | -24 | async fn handler(&self) {} +25 | async fn handler(&self) {} | ^^^^^ diff --git a/axum-macros/tests/debug_handler/fail/multiple_body_extractors.rs b/axum-macros/tests/debug_handler/fail/multiple_body_extractors.rs deleted file mode 100644 index 875c75407e..0000000000 --- a/axum-macros/tests/debug_handler/fail/multiple_body_extractors.rs +++ /dev/null @@ -1,7 +0,0 @@ -use axum_macros::debug_handler; -use axum::body::Bytes; - -#[debug_handler] -async fn handler(_: String, _: Bytes) {} - -fn main() {} diff --git a/axum-macros/tests/debug_handler/fail/multiple_body_extractors.stderr b/axum-macros/tests/debug_handler/fail/multiple_body_extractors.stderr deleted file mode 100644 index 098f3675d0..0000000000 --- a/axum-macros/tests/debug_handler/fail/multiple_body_extractors.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: Only one body extractor can be applied - --> tests/debug_handler/fail/multiple_body_extractors.rs:5:18 - | -5 | async fn handler(_: String, _: Bytes) {} - | ^^^^^^^^^ - -error: Only one body extractor can be applied - --> tests/debug_handler/fail/multiple_body_extractors.rs:5:29 - | -5 | async fn handler(_: String, _: Bytes) {} - | ^^^^^^^^ diff --git a/axum-macros/tests/debug_handler/fail/request_not_last.rs b/axum-macros/tests/debug_handler/fail/request_not_last.rs deleted file mode 100644 index 153d35ef3f..0000000000 --- a/axum-macros/tests/debug_handler/fail/request_not_last.rs +++ /dev/null @@ -1,7 +0,0 @@ -use axum::{body::Body, extract::Extension, http::Request}; -use axum_macros::debug_handler; - -#[debug_handler] -async fn handler(_: Request, _: Extension) {} - -fn main() {} diff --git a/axum-macros/tests/debug_handler/fail/request_not_last.stderr b/axum-macros/tests/debug_handler/fail/request_not_last.stderr deleted file mode 100644 index a3482e6486..0000000000 --- a/axum-macros/tests/debug_handler/fail/request_not_last.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `Request` extractor should always be last - --> tests/debug_handler/fail/request_not_last.rs:5:18 - | -5 | async fn handler(_: Request, _: Extension) {} - | ^^^^^^^^^^^^^^^^ diff --git a/axum-macros/tests/debug_handler/fail/wrong_return_type.stderr b/axum-macros/tests/debug_handler/fail/wrong_return_type.stderr index c3ca7e1e80..89a5ed55ad 100644 --- a/axum-macros/tests/debug_handler/fail/wrong_return_type.stderr +++ b/axum-macros/tests/debug_handler/fail/wrong_return_type.stderr @@ -13,7 +13,7 @@ error[E0277]: the trait bound `bool: IntoResponse` is not satisfied (Response<()>, T1, T2, R) (Response<()>, T1, T2, T3, R) (Response<()>, T1, T2, T3, T4, R) - and 123 others + and 122 others note: required by a bound in `__axum_macros_check_handler_into_response::{closure#0}::check` --> tests/debug_handler/fail/wrong_return_type.rs:4:23 | diff --git a/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs b/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs index 4941f59638..c4be8b52af 100644 --- a/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs +++ b/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs @@ -1,8 +1,4 @@ -use axum::{ - async_trait, - extract::{FromRequest, RequestParts}, - response::IntoResponse, -}; +use axum::{async_trait, extract::FromRequest, http::Request, response::IntoResponse}; use axum_macros::debug_handler; fn main() {} @@ -122,12 +118,12 @@ impl A { #[async_trait] impl FromRequest for A where - B: Send, + B: Send + 'static, S: Send + Sync, { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: Request, _state: &S) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/debug_handler/pass/self_receiver.rs b/axum-macros/tests/debug_handler/pass/self_receiver.rs index a926eb7f44..e7bf81ce6c 100644 --- a/axum-macros/tests/debug_handler/pass/self_receiver.rs +++ b/axum-macros/tests/debug_handler/pass/self_receiver.rs @@ -1,6 +1,7 @@ use axum::{ async_trait, - extract::{FromRequest, RequestParts}, + extract::FromRequest, + http::Request, }; use axum_macros::debug_handler; @@ -9,12 +10,25 @@ struct A; #[async_trait] impl FromRequest for A where - B: Send, + B: Send + 'static, S: Send + Sync, { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: Request, _state: &S) -> Result { + unimplemented!() + } +} + +#[async_trait] +impl FromRequest for Box +where + B: Send + 'static, + S: Send + Sync, +{ + type Rejection = (); + + async fn from_request(_req: Request, _state: &S) -> Result { unimplemented!() } } @@ -22,6 +36,9 @@ where impl A { #[debug_handler] async fn handler(self) {} + + #[debug_handler] + async fn handler_with_qualified_self(self: Box) {} } fn main() {} diff --git a/axum-macros/tests/debug_handler/pass/set_state.rs b/axum-macros/tests/debug_handler/pass/set_state.rs index 12afaf1059..5c84dbd25b 100644 --- a/axum-macros/tests/debug_handler/pass/set_state.rs +++ b/axum-macros/tests/debug_handler/pass/set_state.rs @@ -1,6 +1,7 @@ use axum_macros::debug_handler; -use axum::extract::{FromRef, FromRequest, RequestParts}; +use axum::extract::{FromRef, FromRequest}; use axum::async_trait; +use axum::http::Request; #[debug_handler(state = AppState)] async fn handler(_: A) {} @@ -13,13 +14,13 @@ struct A; #[async_trait] impl FromRequest for A where - B: Send, + B: Send + 'static, S: Send + Sync, AppState: FromRef, { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: Request, _state: &S) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/typed_path/fail/not_deserialize.stderr b/axum-macros/tests/typed_path/fail/not_deserialize.stderr index 9aabf3625f..91f3c3e30a 100644 --- a/axum-macros/tests/typed_path/fail/not_deserialize.stderr +++ b/axum-macros/tests/typed_path/fail/not_deserialize.stderr @@ -15,5 +15,5 @@ error[E0277]: the trait bound `for<'de> MyPath: serde::de::Deserialize<'de>` is (T0, T1, T2, T3) and 138 others = note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `MyPath` - = note: required because of the requirements on the impl of `FromRequest` for `axum::extract::Path` + = note: required because of the requirements on the impl of `FromRequestParts` for `axum::extract::Path` = note: this error originates in the derive macro `TypedPath` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/axum-macros/tests/typed_path/pass/option_result.rs b/axum-macros/tests/typed_path/pass/option_result.rs index 252bde137f..bd4c6dc282 100644 --- a/axum-macros/tests/typed_path/pass/option_result.rs +++ b/axum-macros/tests/typed_path/pass/option_result.rs @@ -16,7 +16,6 @@ async fn result_handler(_: Result) {} #[typed_path("/users")] struct UsersIndex; -#[axum_macros::debug_handler] async fn result_handler_unit_struct(_: Result) {} fn main() {