From fd57d871aa55f4774827643358109e7c1414b686 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 20 Dec 2025 18:40:34 +0100 Subject: [PATCH] Improve error messages with #[diagnostic::do_not_recommend] (#3588) --- axum-core/src/extract/option.rs | 4 ++++ axum-core/src/extract/request_parts.rs | 3 +++ axum-core/src/extract/tuple.rs | 3 +++ .../fail/argument_not_extractor.stderr | 16 ++++++++-------- .../fail/extension_not_clone.stderr | 17 ++++++++--------- .../fail/generic_without_via.stderr | 3 --- .../fail/generic_without_via_rejection.stderr | 3 --- ...verride_rejection_on_enum_without_via.stderr | 6 ------ .../fail/parts_extracting_body.stderr | 16 ++++++++-------- axum/src/extract/nested_path.rs | 1 + axum/src/handler/mod.rs | 4 ++++ axum/src/routing/method_routing.rs | 1 + 12 files changed, 40 insertions(+), 37 deletions(-) diff --git a/axum-core/src/extract/option.rs b/axum-core/src/extract/option.rs index fcedbe98..c2895857 100644 --- a/axum-core/src/extract/option.rs +++ b/axum-core/src/extract/option.rs @@ -35,6 +35,9 @@ pub trait OptionalFromRequest: Sized { ) -> impl Future, Self::Rejection>> + Send; } +// Compiler hint just says that there is an impl for Option, not mentioning +// the bounds, which is not very helpful. +#[diagnostic::do_not_recommend] impl FromRequestParts for Option where T: OptionalFromRequestParts, @@ -51,6 +54,7 @@ where } } +#[diagnostic::do_not_recommend] impl FromRequest for Option where T: OptionalFromRequest, diff --git a/axum-core/src/extract/request_parts.rs b/axum-core/src/extract/request_parts.rs index 498b1edf..5f09dde2 100644 --- a/axum-core/src/extract/request_parts.rs +++ b/axum-core/src/extract/request_parts.rs @@ -65,6 +65,7 @@ where } } +#[diagnostic::do_not_recommend] // pretty niche impl impl FromRequest for BytesMut where S: Send + Sync, @@ -136,6 +137,7 @@ where } } +#[diagnostic::do_not_recommend] // pretty niche impl impl FromRequestParts for Parts where S: Send + Sync, @@ -147,6 +149,7 @@ where } } +#[diagnostic::do_not_recommend] // pretty niche impl impl FromRequestParts for Extensions where S: Send + Sync, diff --git a/axum-core/src/extract/tuple.rs b/axum-core/src/extract/tuple.rs index ccfd21d0..abbe181a 100644 --- a/axum-core/src/extract/tuple.rs +++ b/axum-core/src/extract/tuple.rs @@ -3,6 +3,7 @@ use crate::response::{IntoResponse, Response}; use http::request::Parts; use std::{convert::Infallible, future::Future}; +#[diagnostic::do_not_recommend] impl FromRequestParts for () where S: Send + Sync, @@ -18,6 +19,7 @@ macro_rules! impl_from_request { ( [$($ty:ident),*], $last:ident ) => { + #[diagnostic::do_not_recommend] #[allow(non_snake_case, unused_mut, unused_variables)] impl FromRequestParts for ($($ty,)* $last,) where @@ -43,6 +45,7 @@ macro_rules! impl_from_request { // This impl must not be generic over M, otherwise it would conflict with the blanket // implementation of `FromRequest` for `T: FromRequestParts`. + #[diagnostic::do_not_recommend] #[allow(non_snake_case, unused_mut, unused_variables)] impl FromRequest for ($($ty,)* $last,) where 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 127e93ef..681473ea 100644 --- a/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr +++ b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr @@ -7,14 +7,14 @@ error[E0277]: the trait bound `bool: FromRequest<(), axum_core::extract::private = note: Function argument is not a valid axum extractor. See `https://docs.rs/axum/0.8/axum/extract/index.html` for details = help: the following other types implement trait `FromRequestParts`: - `()` implements `FromRequestParts` - `(T1, T2)` implements `FromRequestParts` - `(T1, T2, T3)` implements `FromRequestParts` - `(T1, T2, T3, T4)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5, T6)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5, T6, T7)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5, T6, T7, T8)` implements `FromRequestParts` + `ConnectInfo` implements `FromRequestParts` + `Extension` implements `FromRequestParts` + `HeaderMap` implements `FromRequestParts` + `MatchedPath` implements `FromRequestParts` + `Method` implements `FromRequestParts` + `OriginalUri` implements `FromRequestParts` + `Query` implements `FromRequestParts` + `RawPathParams` implements `FromRequestParts` and $N others = note: required for `bool` to implement `FromRequest<(), axum_core::extract::private::ViaParts>` note: required by a bound in `__axum_macros_check_handler_0_from_request_check` diff --git a/axum-macros/tests/debug_handler/fail/extension_not_clone.stderr b/axum-macros/tests/debug_handler/fail/extension_not_clone.stderr index 3514a788..aaaeba59 100644 --- a/axum-macros/tests/debug_handler/fail/extension_not_clone.stderr +++ b/axum-macros/tests/debug_handler/fail/extension_not_clone.stderr @@ -5,15 +5,14 @@ error[E0277]: the trait bound `NonCloneType: Clone` is not satisfied | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NonCloneType` | = help: the following other types implement trait `FromRequest`: - (T1, T2) - (T1, T2, T3) - (T1, T2, T3, T4) - (T1, T2, T3, T4, T5) - (T1, T2, T3, T4, T5, T6) - (T1, T2, T3, T4, T5, T6, T7) - (T1, T2, T3, T4, T5, T6, T7, T8) - (T1, T2, T3, T4, T5, T6, T7, T8, T9) - and $N others + Body + Form + Json + RawForm + Result>::Rejection> + String + axum::body::Bytes + axum::http::Request = note: required for `Extension` to implement `FromRequestParts<()>` = note: required for `Extension` to implement `FromRequest<(), axum_core::extract::private::ViaParts>` note: required by a bound in `__axum_macros_check_test_extension_non_clone_0_from_request_check` diff --git a/axum-macros/tests/from_request/fail/generic_without_via.stderr b/axum-macros/tests/from_request/fail/generic_without_via.stderr index f45350de..81393549 100644 --- a/axum-macros/tests/from_request/fail/generic_without_via.stderr +++ b/axum-macros/tests/from_request/fail/generic_without_via.stderr @@ -13,9 +13,6 @@ error[E0277]: the trait bound `fn(Extractor<()>) -> impl Future {fo | required by a bound introduced by this call | = note: Consider using `#[axum::debug_handler]` to improve the error message - = help: the following other types implement trait `Handler`: - `Layered` implements `Handler` - `MethodRouter` implements `Handler<(), S>` note: required by a bound in `axum::routing::get` --> $WORKSPACE/axum/src/routing/method_routing.rs | diff --git a/axum-macros/tests/from_request/fail/generic_without_via_rejection.stderr b/axum-macros/tests/from_request/fail/generic_without_via_rejection.stderr index fe123895..8d7b07fb 100644 --- a/axum-macros/tests/from_request/fail/generic_without_via_rejection.stderr +++ b/axum-macros/tests/from_request/fail/generic_without_via_rejection.stderr @@ -13,9 +13,6 @@ error[E0277]: the trait bound `fn(Extractor<()>) -> impl Future {fo | required by a bound introduced by this call | = note: Consider using `#[axum::debug_handler]` to improve the error message - = help: the following other types implement trait `Handler`: - `Layered` implements `Handler` - `MethodRouter` implements `Handler<(), S>` note: required by a bound in `axum::routing::get` --> $WORKSPACE/axum/src/routing/method_routing.rs | diff --git a/axum-macros/tests/from_request/fail/override_rejection_on_enum_without_via.stderr b/axum-macros/tests/from_request/fail/override_rejection_on_enum_without_via.stderr index 5b4c2ea7..11f88c7c 100644 --- a/axum-macros/tests/from_request/fail/override_rejection_on_enum_without_via.stderr +++ b/axum-macros/tests/from_request/fail/override_rejection_on_enum_without_via.stderr @@ -13,9 +13,6 @@ error[E0277]: the trait bound `fn(MyExtractor) -> impl Future {hand | required by a bound introduced by this call | = note: Consider using `#[axum::debug_handler]` to improve the error message - = help: the following other types implement trait `Handler`: - `Layered` implements `Handler` - `MethodRouter` implements `Handler<(), S>` note: required by a bound in `axum::routing::get` --> $WORKSPACE/axum/src/routing/method_routing.rs | @@ -35,9 +32,6 @@ error[E0277]: the trait bound `fn(Result) -> impl Futu | required by a bound introduced by this call | = note: Consider using `#[axum::debug_handler]` to improve the error message - = help: the following other types implement trait `Handler`: - `Layered` implements `Handler` - `MethodRouter` implements `Handler<(), S>` note: required by a bound in `MethodRouter::::post` --> $WORKSPACE/axum/src/routing/method_routing.rs | diff --git a/axum-macros/tests/from_request/fail/parts_extracting_body.stderr b/axum-macros/tests/from_request/fail/parts_extracting_body.stderr index c76f853e..e97be258 100644 --- a/axum-macros/tests/from_request/fail/parts_extracting_body.stderr +++ b/axum-macros/tests/from_request/fail/parts_extracting_body.stderr @@ -7,14 +7,14 @@ error[E0277]: the trait bound `String: FromRequestParts<_>` is not satisfied = note: Function argument is not a valid axum extractor. See `https://docs.rs/axum/0.8/axum/extract/index.html` for details = help: the following other types implement trait `FromRequestParts`: - `()` implements `FromRequestParts` - `(T1, T2)` implements `FromRequestParts` - `(T1, T2, T3)` implements `FromRequestParts` - `(T1, T2, T3, T4)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5, T6)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5, T6, T7)` implements `FromRequestParts` - `(T1, T2, T3, T4, T5, T6, T7, T8)` implements `FromRequestParts` + `ConnectInfo` implements `FromRequestParts` + `Extension` implements `FromRequestParts` + `Extractor` implements `FromRequestParts` + `HeaderMap` implements `FromRequestParts` + `MatchedPath` implements `FromRequestParts` + `Method` implements `FromRequestParts` + `OriginalUri` implements `FromRequestParts` + `Query` implements `FromRequestParts` and $N others error[E0282]: type annotations needed diff --git a/axum/src/extract/nested_path.rs b/axum/src/extract/nested_path.rs index 1d2c255e..713f03ee 100644 --- a/axum/src/extract/nested_path.rs +++ b/axum/src/extract/nested_path.rs @@ -47,6 +47,7 @@ impl NestedPath { } } +#[diagnostic::do_not_recommend] // pretty niche type impl FromRequestParts for NestedPath where S: Send + Sync, diff --git a/axum/src/handler/mod.rs b/axum/src/handler/mod.rs index e99be5f8..36c06b8d 100644 --- a/axum/src/handler/mod.rs +++ b/axum/src/handler/mod.rs @@ -204,6 +204,7 @@ pub trait Handler: Clone + Send + Sync + Sized + 'static { } } +#[diagnostic::do_not_recommend] impl Handler<((),), S> for F where F: FnOnce() -> Fut + Clone + Send + Sync + 'static, @@ -221,6 +222,7 @@ macro_rules! impl_handler { ( [$($ty:ident),*], $last:ident ) => { + #[diagnostic::do_not_recommend] #[allow(non_snake_case, unused_mut)] impl Handler<(M, $($ty,)* $last,), S> for F where @@ -265,6 +267,7 @@ mod private { pub enum IntoResponseHandler {} } +#[diagnostic::do_not_recommend] impl Handler for T where T: IntoResponse + Clone + Send + Sync + 'static, @@ -310,6 +313,7 @@ where } } +#[diagnostic::do_not_recommend] impl Handler for Layered where L: Layer> + Clone + Send + Sync + 'static, diff --git a/axum/src/routing/method_routing.rs b/axum/src/routing/method_routing.rs index 1ab10db5..db3ef85f 100644 --- a/axum/src/routing/method_routing.rs +++ b/axum/src/routing/method_routing.rs @@ -1303,6 +1303,7 @@ where } } +#[diagnostic::do_not_recommend] impl Handler<(), S> for MethodRouter where S: Clone + 'static,