Skip to content

Commit e0d4bc0

Browse files
Address review comments
Co-authored-by: Michael Goulet <[email protected]>
1 parent fe719f9 commit e0d4bc0

File tree

8 files changed

+49
-56
lines changed

8 files changed

+49
-56
lines changed

compiler/rustc_ast/src/attr/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl Attribute {
9999
}
100100
}
101101

102-
pub fn is_path(&self, name: &[Symbol]) -> bool {
102+
pub fn path_matches(&self, name: &[Symbol]) -> bool {
103103
match &self.kind {
104104
AttrKind::Normal(normal) => {
105105
normal.item.path.segments.len() == name.len()
@@ -109,7 +109,7 @@ impl Attribute {
109109
.segments
110110
.iter()
111111
.zip(name)
112-
.all(|(s, n)| s.ident == Ident::with_dummy_span(*n))
112+
.all(|(s, n)| s.args.is_none() && s.ident.name == *n)
113113
}
114114
AttrKind::DocComment(..) => false,
115115
}

compiler/rustc_hir_analysis/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ hir_analysis_copy_impl_on_type_with_dtor =
5757
the trait `Copy` cannot be implemented for this type; the type has a destructor
5858
.label = `Copy` not allowed on types with destructors
5959
60-
hir_analysis_diagnostic_on_unimplemented_only_for_traits =
61-
`#[diagnostic::on_unimplemented]` can only be applied to trait definitions
62-
6360
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
6461
6562
hir_analysis_drop_impl_on_wrong_item =

compiler/rustc_hir_analysis/src/check/check.rs

+2-24
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1616
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1717
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
1818
use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
19-
use rustc_macros::LintDiagnostic;
2019
use rustc_middle::hir::nested_filter;
2120
use rustc_middle::middle::stability::EvalResult;
2221
use rustc_middle::traits::DefiningAnchor;
@@ -28,9 +27,7 @@ use rustc_middle::ty::{
2827
self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
2928
TypeVisitableExt,
3029
};
31-
use rustc_session::lint::builtin::{
32-
UNINHABITED_STATIC, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNSUPPORTED_CALLING_CONVENTIONS,
33-
};
30+
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
3431
use rustc_span::symbol::sym;
3532
use rustc_span::{self, Span};
3633
use rustc_target::abi::FieldIdx;
@@ -43,10 +40,6 @@ use rustc_type_ir::fold::TypeFoldable;
4340

4441
use std::ops::ControlFlow;
4542

46-
#[derive(LintDiagnostic)]
47-
#[diag(hir_analysis_diagnostic_on_unimplemented_only_for_traits)]
48-
pub struct DiagnosticOnUnimplementedOnlyForTraits;
49-
5043
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
5144
match tcx.sess.target.is_abi_supported(abi) {
5245
Some(true) => (),
@@ -574,22 +567,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
574567
tcx.def_path_str(id.owner_id)
575568
);
576569
let _indenter = indenter();
577-
let def_kind = tcx.def_kind(id.owner_id);
578-
if !matches!(def_kind, DefKind::Trait) {
579-
let item_def_id = id.owner_id.to_def_id();
580-
if let Some(attr) = tcx
581-
.get_attrs_by_path(item_def_id, Box::new([sym::diagnostic, sym::on_unimplemented]))
582-
.next()
583-
{
584-
tcx.emit_spanned_lint(
585-
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
586-
tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()),
587-
vec![attr.span],
588-
DiagnosticOnUnimplementedOnlyForTraits,
589-
);
590-
}
591-
}
592-
match def_kind {
570+
match tcx.def_kind(id.owner_id) {
593571
DefKind::Static(..) => {
594572
tcx.ensure().typeck(id.owner_id.def_id);
595573
maybe_check_static_with_link_section(tcx, id.owner_id.def_id);

compiler/rustc_middle/src/ty/mod.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -2410,18 +2410,17 @@ impl<'tcx> TyCtxt<'tcx> {
24102410
}
24112411
}
24122412

2413-
pub fn get_attrs_by_path(
2413+
pub fn get_attrs_by_path<'attr>(
24142414
self,
2415-
did: impl Into<DefId>,
2416-
attr: Box<[Symbol]>,
2417-
) -> impl Iterator<Item = &'tcx ast::Attribute> {
2418-
let did: DefId = did.into();
2419-
let s = attr[0];
2420-
let filter_fn = move |a: &&ast::Attribute| a.is_path(&attr);
2415+
did: DefId,
2416+
attr: &'attr [Symbol],
2417+
) -> impl Iterator<Item = &'tcx ast::Attribute> + 'attr
2418+
where
2419+
'tcx: 'attr,
2420+
{
2421+
let filter_fn = move |a: &&ast::Attribute| a.path_matches(&attr);
24212422
if let Some(did) = did.as_local() {
24222423
self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn)
2423-
} else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(s) {
2424-
bug!("tried to access the `only_local` attribute `{}` from an extern crate", s);
24252424
} else {
24262425
self.item_attrs(did).iter().filter(filter_fn)
24272426
}

compiler/rustc_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ passes_deprecated_annotation_has_no_effect =
141141
passes_deprecated_attribute =
142142
deprecated attribute must be paired with either stable or unstable attribute
143143
144+
passes_diagnostic_diagnostic_on_unimplemented_only_for_traits =
145+
`#[diagnostic::on_unimplemented]` can only be applied to trait definitions
146+
144147
passes_diagnostic_item_first_defined =
145148
the diagnostic item is first defined here
146149

compiler/rustc_passes/src/check_attr.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::{
1616
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
1717
};
1818
use rustc_hir::{MethodKind, Target, Unsafety};
19+
use rustc_macros::LintDiagnostic;
1920
use rustc_middle::hir::nested_filter;
2021
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
2122
use rustc_middle::query::Providers;
@@ -24,7 +25,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
2425
use rustc_middle::ty::{self, TyCtxt};
2526
use rustc_session::lint::builtin::{
2627
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
27-
UNUSED_ATTRIBUTES,
28+
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
2829
};
2930
use rustc_session::parse::feature_err;
3031
use rustc_span::symbol::{kw, sym, Symbol};
@@ -36,6 +37,10 @@ use rustc_trait_selection::traits::ObligationCtxt;
3637
use std::cell::Cell;
3738
use std::collections::hash_map::Entry;
3839

40+
#[derive(LintDiagnostic)]
41+
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
42+
pub struct DiagnosticOnUnimplementedOnlyForTraits;
43+
3944
pub(crate) fn target_from_impl_item<'tcx>(
4045
tcx: TyCtxt<'tcx>,
4146
impl_item: &hir::ImplItem<'_>,
@@ -104,6 +109,9 @@ impl CheckAttrVisitor<'_> {
104109
let mut seen = FxHashMap::default();
105110
let attrs = self.tcx.hir().attrs(hir_id);
106111
for attr in attrs {
112+
if attr.path_matches(&[sym::diagnostic, sym::on_unimplemented]) {
113+
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target);
114+
}
107115
match attr.name_or_empty() {
108116
sym::do_not_recommend => self.check_do_not_recommend(attr.span, target),
109117
sym::inline => self.check_inline(hir_id, attr, span, target),
@@ -284,6 +292,18 @@ impl CheckAttrVisitor<'_> {
284292
}
285293
}
286294

295+
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
296+
fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) {
297+
if !matches!(target, Target::Trait) {
298+
self.tcx.emit_spanned_lint(
299+
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
300+
hir_id,
301+
attr_span,
302+
DiagnosticOnUnimplementedOnlyForTraits,
303+
);
304+
}
305+
}
306+
287307
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
288308
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
289309
match target {

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

+5-9
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ impl<'tcx> OnUnimplementedDirective {
411411
&& label.is_none()
412412
&& note.is_none()
413413
&& !is_diagnostic_namespace_variant
414-
// disallow filters for now
414+
// FIXME(diagnostic_namespace): disallow filters for now
415415
{
416416
if let Some(items) = item.meta_item_list() {
417417
match Self::parse(
@@ -423,7 +423,7 @@ impl<'tcx> OnUnimplementedDirective {
423423
is_diagnostic_namespace_variant,
424424
) {
425425
Ok(Some(subcommand)) => subcommands.push(subcommand),
426-
Ok(None) => unreachable!(
426+
Ok(None) => bug!(
427427
"This cannot happen for now as we only reach that if `is_diagnostic_namespace_variant` is false"
428428
),
429429
Err(reported) => errored = Some(reported),
@@ -476,11 +476,7 @@ impl<'tcx> OnUnimplementedDirective {
476476
let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented).or_else(|| {
477477
if tcx.features().diagnostic_namespace {
478478
is_diagnostic_namespace_variant = true;
479-
tcx.get_attrs_by_path(
480-
item_def_id,
481-
Box::new([sym::diagnostic, sym::on_unimplemented]),
482-
)
483-
.next()
479+
tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, sym::on_unimplemented]).next()
484480
} else {
485481
None
486482
}
@@ -510,7 +506,7 @@ impl<'tcx> OnUnimplementedDirective {
510506
tcx.emit_spanned_lint(
511507
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
512508
tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()),
513-
vec![attr.span],
509+
attr.span,
514510
NoValueInOnUnimplementedLint,
515511
);
516512
Ok(None)
@@ -519,7 +515,7 @@ impl<'tcx> OnUnimplementedDirective {
519515
tcx.emit_spanned_lint(
520516
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
521517
tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()),
522-
vec![attr.span],
518+
attr.span,
523519
NoValueInOnUnimplementedLint,
524520
);
525521
Ok(None)

tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
warning: malformed `on_unimplemented` attribute
2-
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
3-
|
4-
LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
5-
| ^^^^^^^^^^^^^^^^^^^
6-
|
7-
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
8-
91
warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
102
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1
113
|
124
LL | #[diagnostic::on_unimplemented(message = "Baz")]
135
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
8+
9+
warning: malformed `on_unimplemented` attribute
10+
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
11+
|
12+
LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
13+
| ^^^^^^^^^^^^^^^^^^^
1414

1515
warning: malformed `on_unimplemented` attribute
1616
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50

0 commit comments

Comments
 (0)