Skip to content

Commit dfd6d2a

Browse files
committed
Stabilize #[diagnostic::do_not_recommend]
This commit seeks to stabilize the `#[diagnostic::do_not_recommend]` attribute. This attribute was first proposed as `#[do_not_recommend`] attribute in RFC 2397 (rust-lang/rfcs#2397). It gives the crate authors the ability to not suggest to the compiler to not show certain traits in it's error messages. With the presence of the `#[diagnostic]` tool attribute namespace it was decided to move the attribute there, as that lowers the amount of guarantees the compiler needs to give about the exact way this influences error messages. It turns the attribute into a hint which can be ignored. In addition to the original proposed functionality this attribute now also hides the marked trait in help messages ("This trait is implemented by: "). The attribute does not accept any argument and can only be placed on trait implementations. If it is placed somewhere else a lint warning is emitted and the attribute is otherwise ignored. If an argument is detected a lint warning is emitted and the argument is ignored. This follows the rules outlined by the diagnostic namespace. This attribute allows crates like diesel to improve their error messages drastically. The most common example here is the following error message: ``` error[E0277]: the trait bound `&str: Expression` is not satisfied --> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:53:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `Expression` is not implemented for `&str`, which is required by `&str: AsExpression<Integer>` | = help: the following other types implement trait `Expression`: Bound<T> SelectInt note: required for `&str` to implement `AsExpression<Integer>` --> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:26:13 | LL | impl<T, ST> AsExpression<ST> for T | ^^^^^^^^^^^^^^^^ ^ LL | where LL | T: Expression<SqlType = ST>, | ------------------------ unsatisfied trait bound introduced here ``` By applying the new attribute to the wild card trait implementation of `AsExpression` for `T: Expression` the error message becomes: ``` error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied --> $DIR/as_expression.rs:55:15 | LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str` | = help: the trait `AsExpression<Text>` is implemented for `&str` = help: for that trait implementation, expected `Text`, found `Integer` ``` which makes it much easier for users to understand that they are facing a type mismatch. Other explored example usages included * This standard library error message: rust-lang#128008 * That bevy derived example: https://github.com/rust-lang/rust/blob/e1f306899514ea80abc1d1c9f6a57762afb304a3/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs (No more tuple pyramids) Fixes rust-lang#51992
1 parent 49ac1aa commit dfd6d2a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+55
-235
lines changed

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ declare_features! (
173173
(accepted, destructuring_assignment, "1.59.0", Some(71126)),
174174
/// Allows using the `#[diagnostic]` attribute tool namespace
175175
(accepted, diagnostic_namespace, "1.78.0", Some(111996)),
176+
/// Controls errors in trait implementations.
177+
(accepted, do_not_recommend, "CURRENT_RUSTC_VERSION", Some(51992)),
176178
/// Allows `#[doc(alias = "...")]`.
177179
(accepted, doc_alias, "1.48.0", Some(50146)),
178180
/// Allows `..` in tuple (struct) patterns.

compiler/rustc_feature/src/builtin_attrs.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1192,10 +1192,9 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
11921192
map
11931193
});
11941194

1195-
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
1195+
pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
11961196
match sym {
1197-
sym::on_unimplemented => true,
1198-
sym::do_not_recommend => features.do_not_recommend(),
1197+
sym::on_unimplemented | sym::do_not_recommend => true,
11991198
_ => false,
12001199
}
12011200
}

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,6 @@ declare_features! (
459459
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
460460
/// Allows deref patterns.
461461
(incomplete, deref_patterns, "1.79.0", Some(87121)),
462-
/// Controls errors in trait implementations.
463-
(unstable, do_not_recommend, "1.67.0", Some(51992)),
464462
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
465463
(unstable, doc_auto_cfg, "1.58.0", Some(43781)),
466464
/// Allows `#[doc(cfg(...))]`.

compiler/rustc_resolve/src/macros.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -689,8 +689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
689689
&& let [namespace, attribute, ..] = &*path.segments
690690
&& namespace.ident.name == sym::diagnostic
691691
&& !(attribute.ident.name == sym::on_unimplemented
692-
|| (attribute.ident.name == sym::do_not_recommend
693-
&& self.tcx.features().do_not_recommend()))
692+
|| attribute.ident.name == sym::do_not_recommend)
694693
{
695694
let distance =
696695
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);

library/core/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
//
108108
// Library features:
109109
// tidy-alphabetical-start
110+
#![cfg_attr(bootstrap, feature(do_not_recommend))]
110111
#![feature(array_ptr_get)]
111112
#![feature(asm_experimental_arch)]
112113
#![feature(const_align_of_val)]
@@ -129,7 +130,6 @@
129130
#![feature(const_typed_swap)]
130131
#![feature(core_intrinsics)]
131132
#![feature(coverage_attribute)]
132-
#![feature(do_not_recommend)]
133133
#![feature(internal_impls_macro)]
134134
#![feature(ip)]
135135
#![feature(is_ascii_octdigit)]

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
2-
--> $DIR/as_expression.rs:57:15
2+
--> $DIR/as_expression.rs:55:15
33
|
44
LL | SelectInt.check("bar");
55
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
2-
--> $DIR/as_expression.rs:57:21
2+
--> $DIR/as_expression.rs:55:21
33
|
44
LL | SelectInt.check("bar");
55
| ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
@@ -8,7 +8,7 @@ LL | SelectInt.check("bar");
88
|
99
= help: the trait `AsExpression<Text>` is implemented for `&str`
1010
note: required by a bound in `Foo::check`
11-
--> $DIR/as_expression.rs:48:12
11+
--> $DIR/as_expression.rs:46:12
1212
|
1313
LL | fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
1414
| ----- required by a bound in this associated function
@@ -17,7 +17,7 @@ LL | T: AsExpression<Self::SqlType>,
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
1818

1919
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
20-
--> $DIR/as_expression.rs:57:15
20+
--> $DIR/as_expression.rs:55:15
2121
|
2222
LL | SelectInt.check("bar");
2323
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
@@ -27,7 +27,7 @@ LL | SelectInt.check("bar");
2727
= help: for that trait implementation, expected `Text`, found `Integer`
2828

2929
error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
30-
--> $DIR/as_expression.rs:57:5
30+
--> $DIR/as_expression.rs:55:5
3131
|
3232
LL | SelectInt.check("bar");
3333
| ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
//@ ignore-compare-mode-next-solver (explicit revisions)
33
//@[next] compile-flags: -Znext-solver
44

5-
#![feature(do_not_recommend)]
6-
75
pub trait Expression {
86
type SqlType;
97
}

tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.current.stderr

-25
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.next.stderr

-21
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs

-24
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
2-
--> $DIR/does_not_acccept_args.rs:12:1
2+
--> $DIR/does_not_acccept_args.rs:10:1
33
|
44
LL | #[diagnostic::do_not_recommend(not_accepted)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
88

99
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
10-
--> $DIR/does_not_acccept_args.rs:16:1
10+
--> $DIR/does_not_acccept_args.rs:14:1
1111
|
1212
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
16-
--> $DIR/does_not_acccept_args.rs:20:1
16+
--> $DIR/does_not_acccept_args.rs:18:1
1717
|
1818
LL | #[diagnostic::do_not_recommend(not_accepted(42))]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
2-
--> $DIR/does_not_acccept_args.rs:12:1
2+
--> $DIR/does_not_acccept_args.rs:10:1
33
|
44
LL | #[diagnostic::do_not_recommend(not_accepted)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
88

99
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
10-
--> $DIR/does_not_acccept_args.rs:16:1
10+
--> $DIR/does_not_acccept_args.rs:14:1
1111
|
1212
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
16-
--> $DIR/does_not_acccept_args.rs:20:1
16+
--> $DIR/does_not_acccept_args.rs:18:1
1717
|
1818
LL | #[diagnostic::do_not_recommend(not_accepted(42))]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
//@ ignore-compare-mode-next-solver (explicit revisions)
44
//@[next] compile-flags: -Znext-solver
55

6-
#![feature(do_not_recommend)]
7-
86
trait Foo {}
97
trait Bar {}
108
trait Baz {}

tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.current.stderr

-15
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.next.stderr

-17
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs

-20
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/incorrect-locations.current.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,49 @@
11
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
2-
--> $DIR/incorrect-locations.rs:7:1
2+
--> $DIR/incorrect-locations.rs:6:1
33
|
44
LL | #[diagnostic::do_not_recommend]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
88

99
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
10-
--> $DIR/incorrect-locations.rs:11:1
10+
--> $DIR/incorrect-locations.rs:10:1
1111
|
1212
LL | #[diagnostic::do_not_recommend]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
16-
--> $DIR/incorrect-locations.rs:15:1
16+
--> $DIR/incorrect-locations.rs:14:1
1717
|
1818
LL | #[diagnostic::do_not_recommend]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2020

2121
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
22-
--> $DIR/incorrect-locations.rs:19:1
22+
--> $DIR/incorrect-locations.rs:18:1
2323
|
2424
LL | #[diagnostic::do_not_recommend]
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2626

2727
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
28-
--> $DIR/incorrect-locations.rs:23:1
28+
--> $DIR/incorrect-locations.rs:22:1
2929
|
3030
LL | #[diagnostic::do_not_recommend]
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3232

3333
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
34-
--> $DIR/incorrect-locations.rs:27:1
34+
--> $DIR/incorrect-locations.rs:26:1
3535
|
3636
LL | #[diagnostic::do_not_recommend]
3737
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3838

3939
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
40-
--> $DIR/incorrect-locations.rs:31:1
40+
--> $DIR/incorrect-locations.rs:30:1
4141
|
4242
LL | #[diagnostic::do_not_recommend]
4343
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4444

4545
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
46-
--> $DIR/incorrect-locations.rs:35:1
46+
--> $DIR/incorrect-locations.rs:34:1
4747
|
4848
LL | #[diagnostic::do_not_recommend]
4949
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)