mirror of
https://github.com/tokio-rs/axum.git
synced 2025-01-05 18:27:07 +01:00
Fix debug_handler
for Result<impl IntoResponse, Error>
and friends (#588)
Fixes #587
This commit is contained in:
parent
628921bcad
commit
cbb34869d8
3 changed files with 165 additions and 11 deletions
|
@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
- None.
|
- Fix `Result<impl IntoResponse, Error>` generating invalid code ([#588])
|
||||||
|
|
||||||
|
[#588]: https://github.com/tokio-rs/axum/pull/588
|
||||||
|
|
||||||
# 0.3.0 (03. December 2021)
|
# 0.3.0 (03. December 2021)
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,24 @@ mod debug_handler {
|
||||||
};
|
};
|
||||||
let span = ty.span();
|
let span = ty.span();
|
||||||
|
|
||||||
|
let declare_inputs = item_fn
|
||||||
|
.sig
|
||||||
|
.inputs
|
||||||
|
.iter()
|
||||||
|
.filter_map(|arg| match arg {
|
||||||
|
FnArg::Receiver(_) => None,
|
||||||
|
FnArg::Typed(pat_ty) => {
|
||||||
|
let pat = &pat_ty.pat;
|
||||||
|
let ty = &pat_ty.ty;
|
||||||
|
Some(quote! {
|
||||||
|
let #pat: #ty = panic!();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let block = &item_fn.block;
|
||||||
|
|
||||||
let make_value_name = format_ident!(
|
let make_value_name = format_ident!(
|
||||||
"__axum_debug_check_{}_into_response_make_value",
|
"__axum_debug_check_{}_into_response_make_value",
|
||||||
item_fn.sig.ident
|
item_fn.sig.ident
|
||||||
|
@ -259,18 +277,18 @@ mod debug_handler {
|
||||||
let make = if item_fn.sig.asyncness.is_some() {
|
let make = if item_fn.sig.asyncness.is_some() {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
#[allow(warnings)]
|
#[allow(warnings)]
|
||||||
async fn #make_value_name() -> #ty { panic!() }
|
async fn #make_value_name() -> #ty {
|
||||||
}
|
#declare_inputs
|
||||||
} else if let syn::Type::ImplTrait(_) = &**ty {
|
#block
|
||||||
// lets just assume it returns `impl Future`
|
}
|
||||||
quote_spanned! {span=>
|
|
||||||
#[allow(warnings)]
|
|
||||||
fn #make_value_name() -> #ty { async { panic!() } }
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
#[allow(warnings)]
|
#[allow(warnings)]
|
||||||
fn #make_value_name() -> #ty { panic!() }
|
fn #make_value_name() -> #ty {
|
||||||
|
#declare_inputs
|
||||||
|
#block
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -285,7 +303,7 @@ mod debug_handler {
|
||||||
let value = #receiver #make_value_name().await;
|
let value = #receiver #make_value_name().await;
|
||||||
fn check<T>(_: T)
|
fn check<T>(_: T)
|
||||||
where T: ::axum::response::IntoResponse
|
where T: ::axum::response::IntoResponse
|
||||||
{}
|
{}
|
||||||
check(value);
|
check(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,9 +314,11 @@ mod debug_handler {
|
||||||
#make
|
#make
|
||||||
|
|
||||||
let value = #make_value_name().await;
|
let value = #make_value_name().await;
|
||||||
|
|
||||||
fn check<T>(_: T)
|
fn check<T>(_: T)
|
||||||
where T: ::axum::response::IntoResponse
|
where T: ::axum::response::IntoResponse
|
||||||
{}
|
{}
|
||||||
|
|
||||||
check(value);
|
check(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
132
axum-debug/tests/pass/result_impl_into_response.rs
Normal file
132
axum-debug/tests/pass/result_impl_into_response.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
use axum::{
|
||||||
|
async_trait,
|
||||||
|
extract::{FromRequest, RequestParts},
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use axum_debug::debug_handler;
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
fn concrete_future() -> std::future::Ready<Result<impl IntoResponse, ()>> {
|
||||||
|
std::future::ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
fn impl_future() -> impl std::future::Future<Output = Result<impl IntoResponse, ()>> {
|
||||||
|
std::future::ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// === no args ===
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_one() -> Result<impl IntoResponse, ()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_two() -> Result<(), impl IntoResponse> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_three() -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
Ok::<_, ()>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_four() -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
Err::<(), _>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// === args ===
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_one(foo: String) -> Result<impl IntoResponse, ()> {
|
||||||
|
dbg!(foo);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_two(foo: String) -> Result<(), impl IntoResponse> {
|
||||||
|
dbg!(foo);
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_three(foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
dbg!(foo);
|
||||||
|
Ok::<_, ()>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_four(foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
dbg!(foo);
|
||||||
|
Err::<(), _>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// === no args with receiver ===
|
||||||
|
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_one(self) -> Result<impl IntoResponse, ()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_two(self) -> Result<(), impl IntoResponse> {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_three(self) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
Ok::<_, ()>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_no_arg_four(self) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
Err::<(), _>(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === args with receiver ===
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_one(self, foo: String) -> Result<impl IntoResponse, ()> {
|
||||||
|
dbg!(foo);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_two(self, foo: String) -> Result<(), impl IntoResponse> {
|
||||||
|
dbg!(foo);
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_three(self, foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
dbg!(foo);
|
||||||
|
Ok::<_, ()>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[debug_handler]
|
||||||
|
async fn handler_four(self, foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
dbg!(foo);
|
||||||
|
Err::<(), _>(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<B> FromRequest<B> for A
|
||||||
|
where
|
||||||
|
B: Send + 'static,
|
||||||
|
{
|
||||||
|
type Rejection = ();
|
||||||
|
|
||||||
|
async fn from_request(_req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue