Port #[rustc_diagnostic_item] to the new attribute parsers

This commit is contained in:
Jonathan Brouwer 2026-02-12 22:14:49 +01:00
parent bb8b30a5fc
commit cbc661022e
9 changed files with 61 additions and 25 deletions

View file

@ -1103,6 +1103,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEffectiveVisibilityParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;
}
pub(crate) struct RustcDiagnosticItemParser;
impl<S: Stage> SingleAttributeParser<S> for RustcDiagnosticItemParser {
const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Trait),
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::MacroDef),
Allow(Target::TyAlias),
Allow(Target::AssocTy),
Allow(Target::AssocConst),
Allow(Target::Fn),
Allow(Target::Const),
Allow(Target::Mod),
Allow(Target::Impl { of_trait: false }),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: false })),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::Crate),
]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
cx.expected_name_value(cx.attr_span, None);
return None;
};
let Some(value) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};
Some(AttributeKind::RustcDiagnosticItem(value))
}
}
pub(crate) struct RustcSymbolName;
impl<S: Stage> SingleAttributeParser<S> for RustcSymbolName {

View file

@ -203,6 +203,7 @@ attribute_parsers!(
Single<RustcBuiltinMacroParser>,
Single<RustcDefPath>,
Single<RustcDeprecatedSafe2024Parser>,
Single<RustcDiagnosticItemParser>,
Single<RustcForceInlineParser>,
Single<RustcIfThisChangedParser>,
Single<RustcLayoutScalarValidRangeEndParser>,

View file

@ -919,7 +919,7 @@ impl SyntaxExtension {
fn get_hide_backtrace(attrs: &[hir::Attribute]) -> bool {
// FIXME(estebank): instead of reusing `#[rustc_diagnostic_item]` as a proxy, introduce a
// new attribute purely for this under the `#[diagnostic]` namespace.
ast::attr::find_by_name(attrs, sym::rustc_diagnostic_item).is_some()
find_attr!(attrs, AttributeKind::RustcDiagnosticItem(..))
}
/// Constructs a syntax extension with the given properties

View file

@ -1153,6 +1153,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_deprecated_safe_2024]`
RustcDeprecatedSafe2024 { suggestion: Symbol },
/// Represents `#[rustc_diagnostic_item]`
RustcDiagnosticItem(Symbol),
/// Represents `#[rustc_dummy]`.
RustcDummy,

View file

@ -112,6 +112,7 @@ impl AttributeKind {
RustcDelayedBugFromInsideQuery => No,
RustcDenyExplicitImpl(..) => No,
RustcDeprecatedSafe2024 { .. } => Yes,
RustcDiagnosticItem(..) => Yes,
RustcDummy => No,
RustcDumpDefParents => No,
RustcDumpItemBounds => No,

View file

@ -307,6 +307,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcDelayedBugFromInsideQuery
| AttributeKind::RustcDenyExplicitImpl(..)
| AttributeKind::RustcDeprecatedSafe2024 {..}
| AttributeKind::RustcDiagnosticItem(..)
| AttributeKind::RustcDummy
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpItemBounds
@ -398,7 +399,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::panic_handler
| sym::lang
| sym::default_lib_allocator
| sym::rustc_diagnostic_item
| sym::rustc_nonnull_optimization_guaranteed
| sym::rustc_inherit_overflow_checks
| sym::rustc_on_unimplemented

View file

@ -9,20 +9,21 @@
//!
//! * Compiler internal types like `Ty` and `TyCtxt`
use rustc_hir::attrs::AttributeKind;
use rustc_hir::diagnostic_items::DiagnosticItems;
use rustc_hir::{Attribute, CRATE_OWNER_ID, OwnerId};
use rustc_hir::{CRATE_OWNER_ID, OwnerId, find_attr};
use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_span::Symbol;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::{Symbol, sym};
use crate::errors::DuplicateDiagnosticItemInCrate;
fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
let attrs = tcx.hir_attrs(owner.into());
if let Some(name) = extract(attrs) {
if let Some(name) = find_attr!(attrs, AttributeKind::RustcDiagnosticItem(name) => name) {
// insert into our table
collect_item(tcx, diagnostic_items, name, owner.to_def_id());
collect_item(tcx, diagnostic_items, *name, owner.to_def_id());
}
}
@ -53,13 +54,6 @@ fn report_duplicate_item(
});
}
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(attrs: &[Attribute]) -> Option<Symbol> {
attrs.iter().find_map(|attr| {
if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }
})
}
/// Traverse and collect the diagnostic items in the current
fn diagnostic_items(tcx: TyCtxt<'_>, _: LocalCrate) -> DiagnosticItems {
// Initialize the collector.

View file

@ -1425,14 +1425,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// a note about editions
let note = if let Some(did) = did {
let requires_note = !did.is_local()
&& this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any(
|attr| {
[sym::TryInto, sym::TryFrom, sym::FromIterator]
.map(|x| Some(x))
.contains(&attr.value_str())
},
&& find_attr!(
this.tcx.get_all_attrs(did),
AttributeKind::RustcDiagnosticItem(
sym::TryInto | sym::TryFrom | sym::FromIterator
)
);
requires_note.then(|| {
format!(
"'{}' is included in the prelude starting in Edition 2021",

View file

@ -21,7 +21,7 @@ use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::{MissingLifetimeKind, PrimTy};
use rustc_hir::{MissingLifetimeKind, PrimTy, find_attr};
use rustc_middle::ty;
use rustc_session::{Session, lint};
use rustc_span::edit_distance::{edit_distance, find_best_match_for_name};
@ -2446,10 +2446,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
.iter()
.filter_map(|candidate| candidate.did)
.find(|did| {
self.r
.tcx
.get_attrs(*did, sym::rustc_diagnostic_item)
.any(|attr| attr.value_str() == Some(sym::Default))
find_attr!(
self.r.tcx.get_all_attrs(*did),
AttributeKind::RustcDiagnosticItem(sym::Default)
)
});
let Some(default_trait) = default_trait else {
return;