From f72c298ee8b31b5b4fdcff3f69a7481ad3b075e3 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 c537e721..0ffd277f 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, @@ -50,6 +53,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 b2a5c14a..ea6a2214 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, @@ -134,6 +135,7 @@ where } } +#[diagnostic::do_not_recommend] // pretty niche impl impl FromRequestParts for Parts where S: Send + Sync, @@ -145,6 +147,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 56a4fff5..29cb4765 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 81bec918..1e13b8e4 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`, which is required by `Extension: FromRequest<(), _>` | = 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 daabab09..ecb18877 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 66f90281..c162a915 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 e70248f3..418b5a05 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 3008270f..10a832be 100644 --- a/axum-macros/tests/from_request/fail/parts_extracting_body.stderr +++ b/axum-macros/tests/from_request/fail/parts_extracting_body.stderr @@ -7,12 +7,12 @@ 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 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 5dee1e47..338d89c4 100644 --- a/axum/src/routing/method_routing.rs +++ b/axum/src/routing/method_routing.rs @@ -1306,6 +1306,7 @@ where } } +#[diagnostic::do_not_recommend] impl Handler<(), S> for MethodRouter where S: Clone + 'static,