Skip to content

Commit b54dd08

Browse files
committed
Auto merge of #125326 - weiznich:move/do_not_recommend_to_diganostic_namespace, r=compiler-errors
Move `#[do_not_recommend]` to the `#[diagnostic]` namespace This commit moves the `#[do_not_recommend]` attribute to the `#[diagnostic]` namespace. It still requires `#![feature(do_not_recommend)]` to work. r? `@compiler-errors`
2 parents 54cdc13 + 2cff3e9 commit b54dd08

File tree

22 files changed

+228
-209
lines changed

22 files changed

+228
-209
lines changed

compiler/rustc_ast/src/attr/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::util::literal::escape_string_symbol;
1313
use rustc_index::bit_set::GrowableBitSet;
1414
use rustc_span::symbol::{sym, Ident, Symbol};
1515
use rustc_span::Span;
16+
use smallvec::{smallvec, SmallVec};
1617
use std::iter;
1718
use std::sync::atomic::{AtomicU32, Ordering};
1819
use thin_vec::{thin_vec, ThinVec};
@@ -87,10 +88,20 @@ impl Attribute {
8788
AttrKind::DocComment(..) => None,
8889
}
8990
}
91+
9092
pub fn name_or_empty(&self) -> Symbol {
9193
self.ident().unwrap_or_else(Ident::empty).name
9294
}
9395

96+
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
97+
match &self.kind {
98+
AttrKind::Normal(normal) => {
99+
normal.item.path.segments.iter().map(|s| s.ident.name).collect()
100+
}
101+
AttrKind::DocComment(..) => smallvec![sym::doc],
102+
}
103+
}
104+
94105
#[inline]
95106
pub fn has_name(&self, name: Symbol) -> bool {
96107
match &self.kind {

compiler/rustc_feature/src/builtin_attrs.rs

-6
Original file line numberDiff line numberDiff line change
@@ -515,12 +515,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
515515
EncodeCrossCrate::Yes, experimental!(deprecated_safe),
516516
),
517517

518-
// RFC 2397
519-
gated!(
520-
do_not_recommend, Normal, template!(Word), WarnFollowing,
521-
EncodeCrossCrate::Yes, experimental!(do_not_recommend)
522-
),
523-
524518
// `#[cfi_encoding = ""]`
525519
gated!(
526520
cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding,

compiler/rustc_middle/src/ty/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1814,6 +1814,11 @@ impl<'tcx> TyCtxt<'tcx> {
18141814
self.get_attrs(did, attr).next().is_some()
18151815
}
18161816

1817+
/// Determines whether an item is annotated with a multi-segement attribute
1818+
pub fn has_attrs_with_path(self, did: impl Into<DefId>, attrs: &[Symbol]) -> bool {
1819+
self.get_attrs_by_path(did.into(), attrs).next().is_some()
1820+
}
1821+
18171822
/// Returns `true` if this is an `auto trait`.
18181823
pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
18191824
self.trait_def(trait_def_id).has_auto_impl

compiler/rustc_passes/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ passes_implied_feature_not_exist =
341341
feature `{$implied_by}` implying `{$feature}` does not exist
342342
343343
passes_incorrect_do_not_recommend_location =
344-
`#[do_not_recommend]` can only be placed on trait implementations
344+
`#[diagnostic::do_not_recommend]` can only be placed on trait implementations
345345
346346
passes_incorrect_meta_item = expected a quoted string literal
347347
passes_incorrect_meta_item_suggestion = consider surrounding this with quotes

compiler/rustc_passes/src/check_attr.rs

+75-62
Original file line numberDiff line numberDiff line change
@@ -113,92 +113,96 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
113113
let mut seen = FxHashMap::default();
114114
let attrs = self.tcx.hir().attrs(hir_id);
115115
for attr in attrs {
116-
if attr.path_matches(&[sym::diagnostic, sym::on_unimplemented]) {
117-
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target);
118-
}
119-
match attr.name_or_empty() {
120-
sym::do_not_recommend => self.check_do_not_recommend(attr.span, target),
121-
sym::inline => self.check_inline(hir_id, attr, span, target),
122-
sym::coverage => self.check_coverage(hir_id, attr, span, target),
123-
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
124-
sym::marker => self.check_marker(hir_id, attr, span, target),
125-
sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs),
126-
sym::thread_local => self.check_thread_local(attr, span, target),
127-
sym::track_caller => {
116+
match attr.path().as_slice() {
117+
[sym::diagnostic, sym::do_not_recommend] => {
118+
self.check_do_not_recommend(attr.span, hir_id, target)
119+
}
120+
[sym::diagnostic, sym::on_unimplemented] => {
121+
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
122+
}
123+
[sym::inline] => self.check_inline(hir_id, attr, span, target),
124+
[sym::coverage] => self.check_coverage(hir_id, attr, span, target),
125+
[sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target),
126+
[sym::marker] => self.check_marker(hir_id, attr, span, target),
127+
[sym::target_feature] => {
128+
self.check_target_feature(hir_id, attr, span, target, attrs)
129+
}
130+
[sym::thread_local] => self.check_thread_local(attr, span, target),
131+
[sym::track_caller] => {
128132
self.check_track_caller(hir_id, attr.span, attrs, span, target)
129133
}
130-
sym::doc => self.check_doc_attrs(
134+
[sym::doc] => self.check_doc_attrs(
131135
attr,
132136
hir_id,
133137
target,
134138
&mut specified_inline,
135139
&mut doc_aliases,
136140
),
137-
sym::no_link => self.check_no_link(hir_id, attr, span, target),
138-
sym::export_name => self.check_export_name(hir_id, attr, span, target),
139-
sym::rustc_layout_scalar_valid_range_start
140-
| sym::rustc_layout_scalar_valid_range_end => {
141+
[sym::no_link] => self.check_no_link(hir_id, attr, span, target),
142+
[sym::export_name] => self.check_export_name(hir_id, attr, span, target),
143+
[sym::rustc_layout_scalar_valid_range_start]
144+
| [sym::rustc_layout_scalar_valid_range_end] => {
141145
self.check_rustc_layout_scalar_valid_range(attr, span, target)
142146
}
143-
sym::allow_internal_unstable => {
147+
[sym::allow_internal_unstable] => {
144148
self.check_allow_internal_unstable(hir_id, attr, span, target, attrs)
145149
}
146-
sym::debugger_visualizer => self.check_debugger_visualizer(attr, target),
147-
sym::rustc_allow_const_fn_unstable => {
150+
[sym::debugger_visualizer] => self.check_debugger_visualizer(attr, target),
151+
[sym::rustc_allow_const_fn_unstable] => {
148152
self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target)
149153
}
150-
sym::rustc_std_internal_symbol => {
154+
[sym::rustc_std_internal_symbol] => {
151155
self.check_rustc_std_internal_symbol(attr, span, target)
152156
}
153-
sym::naked => self.check_naked(hir_id, attr, span, target),
154-
sym::rustc_never_returns_null_ptr => {
157+
[sym::naked] => self.check_naked(hir_id, attr, span, target),
158+
[sym::rustc_never_returns_null_ptr] => {
155159
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
156160
}
157-
sym::rustc_legacy_const_generics => {
161+
[sym::rustc_legacy_const_generics] => {
158162
self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
159163
}
160-
sym::rustc_lint_query_instability => {
164+
[sym::rustc_lint_query_instability] => {
161165
self.check_rustc_lint_query_instability(hir_id, attr, span, target)
162166
}
163-
sym::rustc_lint_diagnostics => {
167+
[sym::rustc_lint_diagnostics] => {
164168
self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
165169
}
166-
sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(attr, span, target),
167-
sym::rustc_lint_opt_deny_field_access => {
170+
[sym::rustc_lint_opt_ty] => self.check_rustc_lint_opt_ty(attr, span, target),
171+
[sym::rustc_lint_opt_deny_field_access] => {
168172
self.check_rustc_lint_opt_deny_field_access(attr, span, target)
169173
}
170-
sym::rustc_clean
171-
| sym::rustc_dirty
172-
| sym::rustc_if_this_changed
173-
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(attr),
174-
sym::rustc_coinductive
175-
| sym::rustc_must_implement_one_of
176-
| sym::rustc_deny_explicit_impl
177-
| sym::const_trait => self.check_must_be_applied_to_trait(attr, span, target),
178-
sym::cmse_nonsecure_entry => {
174+
[sym::rustc_clean]
175+
| [sym::rustc_dirty]
176+
| [sym::rustc_if_this_changed]
177+
| [sym::rustc_then_this_would_need] => self.check_rustc_dirty_clean(attr),
178+
[sym::rustc_coinductive]
179+
| [sym::rustc_must_implement_one_of]
180+
| [sym::rustc_deny_explicit_impl]
181+
| [sym::const_trait] => self.check_must_be_applied_to_trait(attr, span, target),
182+
[sym::cmse_nonsecure_entry] => {
179183
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
180184
}
181-
sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
182-
sym::must_not_suspend => self.check_must_not_suspend(attr, span, target),
183-
sym::must_use => self.check_must_use(hir_id, attr, target),
184-
sym::rustc_pass_by_value => self.check_pass_by_value(attr, span, target),
185-
sym::rustc_allow_incoherent_impl => {
185+
[sym::collapse_debuginfo] => self.check_collapse_debuginfo(attr, span, target),
186+
[sym::must_not_suspend] => self.check_must_not_suspend(attr, span, target),
187+
[sym::must_use] => self.check_must_use(hir_id, attr, target),
188+
[sym::rustc_pass_by_value] => self.check_pass_by_value(attr, span, target),
189+
[sym::rustc_allow_incoherent_impl] => {
186190
self.check_allow_incoherent_impl(attr, span, target)
187191
}
188-
sym::rustc_has_incoherent_inherent_impls => {
192+
[sym::rustc_has_incoherent_inherent_impls] => {
189193
self.check_has_incoherent_inherent_impls(attr, span, target)
190194
}
191-
sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target),
192-
sym::ffi_const => self.check_ffi_const(attr.span, target),
193-
sym::rustc_const_unstable
194-
| sym::rustc_const_stable
195-
| sym::unstable
196-
| sym::stable
197-
| sym::rustc_allowed_through_unstable_modules
198-
| sym::rustc_promotable => self.check_stability_promotable(attr, target),
199-
sym::link_ordinal => self.check_link_ordinal(attr, span, target),
200-
sym::rustc_confusables => self.check_confusables(attr, target),
201-
sym::rustc_safe_intrinsic => {
195+
[sym::ffi_pure] => self.check_ffi_pure(attr.span, attrs, target),
196+
[sym::ffi_const] => self.check_ffi_const(attr.span, target),
197+
[sym::rustc_const_unstable]
198+
| [sym::rustc_const_stable]
199+
| [sym::unstable]
200+
| [sym::stable]
201+
| [sym::rustc_allowed_through_unstable_modules]
202+
| [sym::rustc_promotable] => self.check_stability_promotable(attr, target),
203+
[sym::link_ordinal] => self.check_link_ordinal(attr, span, target),
204+
[sym::rustc_confusables] => self.check_confusables(attr, target),
205+
[sym::rustc_safe_intrinsic] => {
202206
self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
203207
}
204208
_ => true,
@@ -290,18 +294,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
290294
);
291295
}
292296

293-
/// Checks if `#[do_not_recommend]` is applied on a trait impl.
294-
fn check_do_not_recommend(&self, attr_span: Span, target: Target) -> bool {
295-
if let Target::Impl = target {
296-
true
297-
} else {
298-
self.dcx().emit_err(errors::IncorrectDoNotRecommendLocation { span: attr_span });
299-
false
297+
/// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
298+
fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) -> bool {
299+
if !matches!(target, Target::Impl) {
300+
self.tcx.emit_node_span_lint(
301+
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
302+
hir_id,
303+
attr_span,
304+
errors::IncorrectDoNotRecommendLocation,
305+
);
300306
}
307+
true
301308
}
302309

303310
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
304-
fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) {
311+
fn check_diagnostic_on_unimplemented(
312+
&self,
313+
attr_span: Span,
314+
hir_id: HirId,
315+
target: Target,
316+
) -> bool {
305317
if !matches!(target, Target::Trait) {
306318
self.tcx.emit_node_span_lint(
307319
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
@@ -310,6 +322,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
310322
DiagnosticOnUnimplementedOnlyForTraits,
311323
);
312324
}
325+
true
313326
}
314327

315328
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.

compiler/rustc_passes/src/errors.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@ use rustc_span::{Span, Symbol, DUMMY_SP};
1717
use crate::check_attr::ProcMacroKind;
1818
use crate::lang_items::Duplicate;
1919

20-
#[derive(Diagnostic)]
20+
#[derive(LintDiagnostic)]
2121
#[diag(passes_incorrect_do_not_recommend_location)]
22-
pub struct IncorrectDoNotRecommendLocation {
23-
#[primary_span]
24-
pub span: Span,
25-
}
22+
pub struct IncorrectDoNotRecommendLocation;
2623

2724
#[derive(LintDiagnostic)]
2825
#[diag(passes_outer_crate_level_attr)]

compiler/rustc_resolve/src/macros.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
578578
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
579579
&& let [namespace, attribute, ..] = &*path.segments
580580
&& namespace.ident.name == sym::diagnostic
581-
&& attribute.ident.name != sym::on_unimplemented
581+
&& !(attribute.ident.name == sym::on_unimplemented
582+
|| (attribute.ident.name == sym::do_not_recommend
583+
&& self.tcx.features().do_not_recommend))
582584
{
583585
let distance =
584586
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);

compiler/rustc_trait_selection/src/solve/fulfill.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
380380
source: CandidateSource::Impl(impl_def_id),
381381
result: _,
382382
} = candidate.kind()
383-
&& goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend)
383+
&& goal
384+
.infcx()
385+
.tcx
386+
.has_attrs_with_path(impl_def_id, &[sym::diagnostic, sym::do_not_recommend])
384387
{
385388
return ControlFlow::Break(self.obligation.clone());
386389
}

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
10121012
let mut base_cause = obligation.cause.code().clone();
10131013
loop {
10141014
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
1015-
if self.tcx.has_attr(c.impl_or_alias_def_id, sym::do_not_recommend) {
1015+
if self.tcx.has_attrs_with_path(
1016+
c.impl_or_alias_def_id,
1017+
&[sym::diagnostic, sym::do_not_recommend],
1018+
) {
10161019
let code = (*c.derived.parent_code).clone();
10171020
obligation.cause.map_code(|_| code);
10181021
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl<T> Expression for Bound<T> {
2626
type SqlType = T;
2727
}
2828

29-
#[do_not_recommend]
29+
#[diagnostic::do_not_recommend]
3030
impl<T, ST> AsExpression<ST> for T
3131
where
3232
T: Expression<SqlType = ST>,

tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
#![feature(do_not_recommend)]
22

3-
pub trait Foo {
4-
}
3+
pub trait Foo {}
54

6-
impl Foo for i32 {
7-
}
5+
impl Foo for i32 {}
86

9-
pub trait Bar {
10-
}
7+
pub trait Bar {}
118

12-
#[do_not_recommend]
13-
impl<T: Foo> Bar for T {
14-
}
9+
#[diagnostic::do_not_recommend]
10+
impl<T: Foo> Bar for T {}
1511

1612
fn stuff<T: Bar>(_: T) {}
1713

tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr tests/ui/diagnostic_namespace/do_not_recommend/feature-gate-do_not_recommend.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0277]: the trait bound `u8: Bar` is not satisfied
2-
--> $DIR/feature-gate-do_not_recommend.rs:19:11
2+
--> $DIR/feature-gate-do_not_recommend.rs:15:11
33
|
44
LL | stuff(1u8);
55
| ^^^ the trait `Bar` is not implemented for `u8`
66
|
77
note: required by a bound in `stuff`
8-
--> $DIR/feature-gate-do_not_recommend.rs:16:13
8+
--> $DIR/feature-gate-do_not_recommend.rs:12:13
99
|
1010
LL | fn stuff<T: Bar>(_: T) {}
1111
| ^^^ required by this bound in `stuff`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//@ check-pass
2+
#![feature(do_not_recommend)]
3+
4+
#[diagnostic::do_not_recommend]
5+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
6+
const CONST: () = ();
7+
8+
#[diagnostic::do_not_recommend]
9+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
10+
static STATIC: () = ();
11+
12+
#[diagnostic::do_not_recommend]
13+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
14+
type Type = ();
15+
16+
#[diagnostic::do_not_recommend]
17+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
18+
enum Enum {}
19+
20+
#[diagnostic::do_not_recommend]
21+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
22+
extern "C" {}
23+
24+
#[diagnostic::do_not_recommend]
25+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
26+
fn fun() {}
27+
28+
#[diagnostic::do_not_recommend]
29+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
30+
struct Struct {}
31+
32+
#[diagnostic::do_not_recommend]
33+
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
34+
trait Trait {}
35+
36+
#[diagnostic::do_not_recommend]
37+
impl Trait for i32 {}
38+
39+
fn main() {}

0 commit comments

Comments
 (0)