Skip to content

Commit cbb3486

Browse files
authored
Fix debug_handler for Result<impl IntoResponse, Error> and friends (#588)
Fixes #587
1 parent 628921b commit cbb3486

File tree

3 files changed

+165
-11
lines changed

3 files changed

+165
-11
lines changed

axum-debug/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
# Unreleased
99

10-
- None.
10+
- Fix `Result<impl IntoResponse, Error>` generating invalid code ([#588])
11+
12+
[#588]: https://github.com/tokio-rs/axum/pull/588
1113

1214
# 0.3.0 (03. December 2021)
1315

axum-debug/src/lib.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,24 @@ mod debug_handler {
251251
};
252252
let span = ty.span();
253253

254+
let declare_inputs = item_fn
255+
.sig
256+
.inputs
257+
.iter()
258+
.filter_map(|arg| match arg {
259+
FnArg::Receiver(_) => None,
260+
FnArg::Typed(pat_ty) => {
261+
let pat = &pat_ty.pat;
262+
let ty = &pat_ty.ty;
263+
Some(quote! {
264+
let #pat: #ty = panic!();
265+
})
266+
}
267+
})
268+
.collect::<TokenStream>();
269+
270+
let block = &item_fn.block;
271+
254272
let make_value_name = format_ident!(
255273
"__axum_debug_check_{}_into_response_make_value",
256274
item_fn.sig.ident
@@ -259,18 +277,18 @@ mod debug_handler {
259277
let make = if item_fn.sig.asyncness.is_some() {
260278
quote_spanned! {span=>
261279
#[allow(warnings)]
262-
async fn #make_value_name() -> #ty { panic!() }
263-
}
264-
} else if let syn::Type::ImplTrait(_) = &**ty {
265-
// lets just assume it returns `impl Future`
266-
quote_spanned! {span=>
267-
#[allow(warnings)]
268-
fn #make_value_name() -> #ty { async { panic!() } }
280+
async fn #make_value_name() -> #ty {
281+
#declare_inputs
282+
#block
283+
}
269284
}
270285
} else {
271286
quote_spanned! {span=>
272287
#[allow(warnings)]
273-
fn #make_value_name() -> #ty { panic!() }
288+
fn #make_value_name() -> #ty {
289+
#declare_inputs
290+
#block
291+
}
274292
}
275293
};
276294

@@ -285,7 +303,7 @@ mod debug_handler {
285303
let value = #receiver #make_value_name().await;
286304
fn check<T>(_: T)
287305
where T: ::axum::response::IntoResponse
288-
{}
306+
{}
289307
check(value);
290308
}
291309
}
@@ -296,9 +314,11 @@ mod debug_handler {
296314
#make
297315

298316
let value = #make_value_name().await;
317+
299318
fn check<T>(_: T)
300-
where T: ::axum::response::IntoResponse
319+
where T: ::axum::response::IntoResponse
301320
{}
321+
302322
check(value);
303323
}
304324
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use axum::{
2+
async_trait,
3+
extract::{FromRequest, RequestParts},
4+
response::IntoResponse,
5+
};
6+
use axum_debug::debug_handler;
7+
8+
fn main() {}
9+
10+
#[debug_handler]
11+
fn concrete_future() -> std::future::Ready<Result<impl IntoResponse, ()>> {
12+
std::future::ready(Ok(()))
13+
}
14+
15+
#[debug_handler]
16+
fn impl_future() -> impl std::future::Future<Output = Result<impl IntoResponse, ()>> {
17+
std::future::ready(Ok(()))
18+
}
19+
20+
// === no args ===
21+
22+
#[debug_handler]
23+
async fn handler_no_arg_one() -> Result<impl IntoResponse, ()> {
24+
Ok(())
25+
}
26+
27+
#[debug_handler]
28+
async fn handler_no_arg_two() -> Result<(), impl IntoResponse> {
29+
Err(())
30+
}
31+
32+
#[debug_handler]
33+
async fn handler_no_arg_three() -> Result<impl IntoResponse, impl IntoResponse> {
34+
Ok::<_, ()>(())
35+
}
36+
37+
#[debug_handler]
38+
async fn handler_no_arg_four() -> Result<impl IntoResponse, impl IntoResponse> {
39+
Err::<(), _>(())
40+
}
41+
42+
// === args ===
43+
44+
#[debug_handler]
45+
async fn handler_one(foo: String) -> Result<impl IntoResponse, ()> {
46+
dbg!(foo);
47+
Ok(())
48+
}
49+
50+
#[debug_handler]
51+
async fn handler_two(foo: String) -> Result<(), impl IntoResponse> {
52+
dbg!(foo);
53+
Err(())
54+
}
55+
56+
#[debug_handler]
57+
async fn handler_three(foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
58+
dbg!(foo);
59+
Ok::<_, ()>(())
60+
}
61+
62+
#[debug_handler]
63+
async fn handler_four(foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
64+
dbg!(foo);
65+
Err::<(), _>(())
66+
}
67+
68+
// === no args with receiver ===
69+
70+
struct A;
71+
72+
impl A {
73+
#[debug_handler]
74+
async fn handler_no_arg_one(self) -> Result<impl IntoResponse, ()> {
75+
Ok(())
76+
}
77+
78+
#[debug_handler]
79+
async fn handler_no_arg_two(self) -> Result<(), impl IntoResponse> {
80+
Err(())
81+
}
82+
83+
#[debug_handler]
84+
async fn handler_no_arg_three(self) -> Result<impl IntoResponse, impl IntoResponse> {
85+
Ok::<_, ()>(())
86+
}
87+
88+
#[debug_handler]
89+
async fn handler_no_arg_four(self) -> Result<impl IntoResponse, impl IntoResponse> {
90+
Err::<(), _>(())
91+
}
92+
}
93+
94+
// === args with receiver ===
95+
96+
impl A {
97+
#[debug_handler]
98+
async fn handler_one(self, foo: String) -> Result<impl IntoResponse, ()> {
99+
dbg!(foo);
100+
Ok(())
101+
}
102+
103+
#[debug_handler]
104+
async fn handler_two(self, foo: String) -> Result<(), impl IntoResponse> {
105+
dbg!(foo);
106+
Err(())
107+
}
108+
109+
#[debug_handler]
110+
async fn handler_three(self, foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
111+
dbg!(foo);
112+
Ok::<_, ()>(())
113+
}
114+
115+
#[debug_handler]
116+
async fn handler_four(self, foo: String) -> Result<impl IntoResponse, impl IntoResponse> {
117+
dbg!(foo);
118+
Err::<(), _>(())
119+
}
120+
}
121+
122+
#[async_trait]
123+
impl<B> FromRequest<B> for A
124+
where
125+
B: Send + 'static,
126+
{
127+
type Rejection = ();
128+
129+
async fn from_request(_req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
130+
unimplemented!()
131+
}
132+
}

0 commit comments

Comments
 (0)