Skip to content

Commit 2ecfa69

Browse files
authored
Unrolled build for rust-lang#132056
Rollup merge of rust-lang#132056 - weiznich:diagnostic_do_not_recommend_final_tests, r=compiler-errors Stabilize `#[diagnostic::do_not_recommend]` This PR 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 its 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 include: * 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 r? ``@compiler-errors`` This PR also adds a few more tests, makes sure that all the tests are run for the old and new trait solver and adds a check that the attribute does not contain arguments.
2 parents 023521e + ad29947 commit 2ecfa69

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

+300
-152
lines changed

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ declare_features! (
178178
(accepted, destructuring_assignment, "1.59.0", Some(71126)),
179179
/// Allows using the `#[diagnostic]` attribute tool namespace
180180
(accepted, diagnostic_namespace, "1.78.0", Some(111996)),
181+
/// Controls errors in trait implementations.
182+
(accepted, do_not_recommend, "CURRENT_RUSTC_VERSION", Some(51992)),
181183
/// Allows `#[doc(alias = "...")]`.
182184
(accepted, doc_alias, "1.48.0", Some(50146)),
183185
/// Allows `..` in tuple (struct) patterns.

compiler/rustc_feature/src/builtin_attrs.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1187,10 +1187,9 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
11871187
map
11881188
});
11891189

1190-
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
1190+
pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
11911191
match sym {
1192-
sym::on_unimplemented => true,
1193-
sym::do_not_recommend => features.do_not_recommend(),
1192+
sym::on_unimplemented | sym::do_not_recommend => true,
11941193
_ => false,
11951194
}
11961195
}

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,6 @@ declare_features! (
462462
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
463463
/// Allows deref patterns.
464464
(incomplete, deref_patterns, "1.79.0", Some(87121)),
465-
/// Controls errors in trait implementations.
466-
(unstable, do_not_recommend, "1.67.0", Some(51992)),
467465
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
468466
(unstable, doc_auto_cfg, "1.58.0", Some(43781)),
469467
/// Allows `#[doc(cfg(...))]`.

compiler/rustc_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ passes_ignored_derived_impls =
357357
passes_implied_feature_not_exist =
358358
feature `{$implied_by}` implying `{$feature}` does not exist
359359
360+
passes_incorrect_do_not_recommend_args =
361+
`#[diagnostic::do_not_recommend]` does not expect any arguments
362+
360363
passes_incorrect_do_not_recommend_location =
361364
`#[diagnostic::do_not_recommend]` can only be placed on trait implementations
362365

compiler/rustc_passes/src/check_attr.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
115115
for attr in attrs {
116116
match attr.path().as_slice() {
117117
[sym::diagnostic, sym::do_not_recommend, ..] => {
118-
self.check_do_not_recommend(attr.span, hir_id, target)
118+
self.check_do_not_recommend(attr.span, hir_id, target, attr, item)
119119
}
120120
[sym::diagnostic, sym::on_unimplemented, ..] => {
121121
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
@@ -348,15 +348,36 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
348348
}
349349

350350
/// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
351-
fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) {
352-
if !matches!(target, Target::Impl) {
351+
fn check_do_not_recommend(
352+
&self,
353+
attr_span: Span,
354+
hir_id: HirId,
355+
target: Target,
356+
attr: &Attribute,
357+
item: Option<ItemLike<'_>>,
358+
) {
359+
if !matches!(target, Target::Impl)
360+
|| matches!(
361+
item,
362+
Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl),.. }))
363+
if _impl.of_trait.is_none()
364+
)
365+
{
353366
self.tcx.emit_node_span_lint(
354367
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
355368
hir_id,
356369
attr_span,
357370
errors::IncorrectDoNotRecommendLocation,
358371
);
359372
}
373+
if !attr.is_word() {
374+
self.tcx.emit_node_span_lint(
375+
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
376+
hir_id,
377+
attr_span,
378+
errors::DoNotRecommendDoesNotExpectArgs,
379+
);
380+
}
360381
}
361382

362383
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition

compiler/rustc_passes/src/errors.rs

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ use crate::lang_items::Duplicate;
2020
#[diag(passes_incorrect_do_not_recommend_location)]
2121
pub(crate) struct IncorrectDoNotRecommendLocation;
2222

23+
#[derive(LintDiagnostic)]
24+
#[diag(passes_incorrect_do_not_recommend_args)]
25+
pub(crate) struct DoNotRecommendDoesNotExpectArgs;
26+
2327
#[derive(Diagnostic)]
2428
#[diag(passes_autodiff_attr)]
2529
pub(crate) struct AutoDiffAttr {

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
@@ -108,12 +108,12 @@
108108
// Library features:
109109
// tidy-alphabetical-start
110110
#![cfg_attr(bootstrap, feature(coverage_attribute))]
111+
#![cfg_attr(bootstrap, feature(do_not_recommend))]
111112
#![feature(array_ptr_get)]
112113
#![feature(asm_experimental_arch)]
113114
#![feature(const_eval_select)]
114115
#![feature(const_typed_swap)]
115116
#![feature(core_intrinsics)]
116-
#![feature(do_not_recommend)]
117117
#![feature(internal_impls_macro)]
118118
#![feature(ip)]
119119
#![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.rs

-21
This file was deleted.

tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr

-25
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
2+
--> $DIR/does_not_acccept_args.rs:10:1
3+
|
4+
LL | #[diagnostic::do_not_recommend(not_accepted)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
8+
9+
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
10+
--> $DIR/does_not_acccept_args.rs:14:1
11+
|
12+
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
16+
--> $DIR/does_not_acccept_args.rs:18:1
17+
|
18+
LL | #[diagnostic::do_not_recommend(not_accepted(42))]
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
warning: 3 warnings emitted
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
2+
--> $DIR/does_not_acccept_args.rs:10:1
3+
|
4+
LL | #[diagnostic::do_not_recommend(not_accepted)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
8+
9+
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
10+
--> $DIR/does_not_acccept_args.rs:14:1
11+
|
12+
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
16+
--> $DIR/does_not_acccept_args.rs:18:1
17+
|
18+
LL | #[diagnostic::do_not_recommend(not_accepted(42))]
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
warning: 3 warnings emitted
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
trait Foo {}
7+
trait Bar {}
8+
trait Baz {}
9+
10+
#[diagnostic::do_not_recommend(not_accepted)]
11+
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
12+
impl<T> Foo for T where T: Send {}
13+
14+
#[diagnostic::do_not_recommend(not_accepted = "foo")]
15+
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
16+
impl<T> Bar for T where T: Send {}
17+
18+
#[diagnostic::do_not_recommend(not_accepted(42))]
19+
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
20+
impl<T> Baz for T where T: Send {}
21+
22+
fn main() {}

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

-17
This file was deleted.

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

-15
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,58 @@
11
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
2-
--> $DIR/incorrect-locations.rs:4: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:8: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:12: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:16: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:20: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:24: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:28: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:32:1
46+
--> $DIR/incorrect-locations.rs:34:1
4747
|
4848
LL | #[diagnostic::do_not_recommend]
4949
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5050

51-
warning: 8 warnings emitted
51+
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
52+
--> $DIR/incorrect-locations.rs:38:1
53+
|
54+
LL | #[diagnostic::do_not_recommend]
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
57+
warning: 9 warnings emitted
5258

0 commit comments

Comments
 (0)