From 5277241d277e1cb5a577bb0ae297c63f23d5dd3d Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Thu, 18 Dec 2025 12:12:31 +0100 Subject: [PATCH 1/2] Port `#[rustc_lint_untracked_query_information]` to attribute parser --- .../src/attributes/rustc_internal.rs | 16 ++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 6 ++++-- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_lint/src/internal.rs | 5 ++++- compiler/rustc_passes/src/check_attr.rs | 4 +--- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 8005dd76b2a3d..ea73b7ad60ef4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -165,6 +165,22 @@ impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability; } +pub(crate) struct RustcLintUntrackedQueryInformationParser; + +impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser { + const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation; +} + pub(crate) struct RustcObjectLifetimeDefaultParser; impl SingleAttributeParser for RustcObjectLifetimeDefaultParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index e5448e7792a88..9b9bd94e11438 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -62,8 +62,9 @@ use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, - RustcLintQueryInstabilityParser, RustcMainParser, RustcNeverReturnsNullPointerParser, - RustcNoImplicitAutorefsParser, RustcObjectLifetimeDefaultParser, RustcScalableVectorParser, + RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, + RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, + RustcObjectLifetimeDefaultParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; @@ -259,6 +260,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 5991fb5ab24e6..afc458e2775fe 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -940,6 +940,9 @@ pub enum AttributeKind { /// Represents `#[rustc_lint_query_instability]` RustcLintQueryInstability, + /// Represents `#[rustc_lint_untracked_query_information]` + RustcLintUntrackedQueryInformation, + /// Represents `#[rustc_main]`. RustcMain, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 64aa9c2a45bc3..1899fe12ecdcc 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -97,6 +97,7 @@ impl AttributeKind { RustcLintOptDenyFieldAccess { .. } => Yes, RustcLintOptTy => Yes, RustcLintQueryInstability => Yes, + RustcLintUntrackedQueryInformation => Yes, RustcMain => No, RustcNeverReturnsNullPointer => Yes, RustcNoImplicitAutorefs => Yes, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index d6f20a4c85a4f..a2fcbd75f50f7 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -106,7 +106,10 @@ impl<'tcx> LateLintPass<'tcx> for QueryStability { ); } - if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) { + if find_attr!( + cx.tcx.get_all_attrs(def_id), + AttributeKind::RustcLintUntrackedQueryInformation + ) { cx.emit_span_lint( UNTRACKED_QUERY_INFORMATION, span, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 33a3477bcf691..7c89982f80775 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -261,6 +261,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcLintOptDenyFieldAccess { .. } | AttributeKind::RustcLintOptTy | AttributeKind::RustcLintQueryInstability + | AttributeKind::RustcLintUntrackedQueryInformation | AttributeKind::RustcNeverReturnsNullPointer | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) @@ -309,9 +310,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_diagnostic_on_const(attr.span(), hir_id, target, item) } [sym::thread_local, ..] => self.check_thread_local(attr, span, target), - [sym::rustc_lint_untracked_query_information, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) - } [sym::rustc_lint_diagnostics, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } From 44cfed7465684c092d7a054bd4accdb8618cca3e Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Thu, 18 Dec 2025 14:20:26 +0100 Subject: [PATCH 2/2] Port `#[rustc_lint_diagnostics]` to attribute parser --- .../src/attributes/rustc_internal.rs | 15 ++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 9 ++++---- .../rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_lint/src/internal.rs | 6 ++--- compiler/rustc_passes/messages.ftl | 7 ------ compiler/rustc_passes/src/check_attr.rs | 23 +------------------ compiler/rustc_passes/src/errors.rs | 10 -------- .../internal-lints/diagnostics_incorrect.rs | 2 +- .../diagnostics_incorrect.stderr | 23 +++++++++++-------- 10 files changed, 42 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index ea73b7ad60ef4..be4e2210c5ee4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -117,6 +117,21 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { } } +pub(crate) struct RustcLintDiagnosticsParser; + +impl NoArgsAttributeParser for RustcLintDiagnosticsParser { + const PATH: &[Symbol] = &[sym::rustc_lint_diagnostics]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintDiagnostics; +} + pub(crate) struct RustcLintOptDenyFieldAccessParser; impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 9b9bd94e11438..a752869c2eb27 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -61,10 +61,10 @@ use crate::attributes::prototype::CustomMirParser; use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, - RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, - RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, - RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, - RustcObjectLifetimeDefaultParser, RustcScalableVectorParser, + RustcLegacyConstGenericsParser, RustcLintDiagnosticsParser, RustcLintOptDenyFieldAccessParser, + RustcLintOptTyParser, RustcLintQueryInstabilityParser, + RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcNeverReturnsNullPointerParser, + RustcNoImplicitAutorefsParser, RustcObjectLifetimeDefaultParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; @@ -258,6 +258,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index afc458e2775fe..1a382d8f124b6 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -931,6 +931,9 @@ pub enum AttributeKind { /// Represents `#[rustc_legacy_const_generics]` RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span }, + /// Represents `#[rustc_lint_diagnostics]` + RustcLintDiagnostics, + /// Represents `#[rustc_lint_opt_deny_field_access]` RustcLintOptDenyFieldAccess { lint_message: Symbol }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 1899fe12ecdcc..7c1e71f258bee 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -94,6 +94,7 @@ impl AttributeKind { RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcLegacyConstGenerics { .. } => Yes, + RustcLintDiagnostics => Yes, RustcLintOptDenyFieldAccess { .. } => Yes, RustcLintOptTy => Yes, RustcLintQueryInstability => Yes, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index a2fcbd75f50f7..68885e14f40d2 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -609,14 +609,14 @@ impl Diagnostics { else { return; }; - let has_attr = cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics); - if !has_attr { + + if !find_attr!(cx.tcx.get_all_attrs(inst.def_id()), AttributeKind::RustcLintDiagnostics) { return; }; for (hir_id, _parent) in cx.tcx.hir_parent_iter(current_id) { if let Some(owner_did) = hir_id.as_owner() - && cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics) + && find_attr!(cx.tcx.get_all_attrs(owner_did), AttributeKind::RustcLintDiagnostics) { // The parent method is marked with `#[rustc_lint_diagnostics]` return; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 7ebfca91d499d..c0106ea0c6276 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -484,13 +484,6 @@ passes_sanitize_attribute_not_allowed = .no_body = function has no body .help = sanitize attribute can be applied to a function (with body), impl block, or module -passes_should_be_applied_to_fn = - attribute should be applied to a function definition - .label = {$on_crate -> - [true] cannot be applied to crates - *[false] not a function definition - } - passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7c89982f80775..945dcec798e3a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -258,6 +258,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcLayoutScalarValidRangeStart(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) + | AttributeKind::RustcLintDiagnostics | AttributeKind::RustcLintOptDenyFieldAccess { .. } | AttributeKind::RustcLintOptTy | AttributeKind::RustcLintQueryInstability @@ -310,9 +311,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_diagnostic_on_const(attr.span(), hir_id, target, item) } [sym::thread_local, ..] => self.check_thread_local(attr, span, target), - [sym::rustc_lint_diagnostics, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) - } [sym::rustc_clean, ..] | [sym::rustc_dirty, ..] | [sym::rustc_if_this_changed, ..] @@ -1228,25 +1226,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Helper function for checking that the provided attribute is only applied to a function or - /// method. - fn check_applied_to_fn_or_method( - &self, - hir_id: HirId, - attr_span: Span, - defn_span: Span, - target: Target, - ) { - let is_function = matches!(target, Target::Fn | Target::Method(..)); - if !is_function { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span, - defn_span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } - } - /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph /// option is passed to the compiler. fn check_rustc_dirty_clean(&self, attr: &Attribute) { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 895cefe672baa..4f97f74c78047 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -80,16 +80,6 @@ pub(crate) struct OuterCrateLevelAttrSuggestion { #[diag(passes_inner_crate_level_attr)] pub(crate) struct InnerCrateLevelAttr; -#[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_fn)] -pub(crate) struct AttrShouldBeAppliedToFn { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, - pub on_crate: bool, -} - #[derive(Diagnostic)] #[diag(passes_non_exhaustive_with_default_field_values)] pub(crate) struct NonExhaustiveWithDefaultFieldValues { diff --git a/tests/ui/internal-lints/diagnostics_incorrect.rs b/tests/ui/internal-lints/diagnostics_incorrect.rs index c1532aa9d57e5..787acdad38842 100644 --- a/tests/ui/internal-lints/diagnostics_incorrect.rs +++ b/tests/ui/internal-lints/diagnostics_incorrect.rs @@ -3,7 +3,7 @@ #![feature(rustc_attrs)] #[rustc_lint_diagnostics] -//~^ ERROR attribute should be applied to a function +//~^ ERROR `#[rustc_lint_diagnostics]` attribute cannot be used on structs struct Foo; impl Foo { diff --git a/tests/ui/internal-lints/diagnostics_incorrect.stderr b/tests/ui/internal-lints/diagnostics_incorrect.stderr index e849ca2829e43..4d509acec7900 100644 --- a/tests/ui/internal-lints/diagnostics_incorrect.stderr +++ b/tests/ui/internal-lints/diagnostics_incorrect.stderr @@ -1,17 +1,20 @@ -error: malformed `rustc_lint_diagnostics` attribute input - --> $DIR/diagnostics_incorrect.rs:10:5 - | -LL | #[rustc_lint_diagnostics(a)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_lint_diagnostics]` - -error: attribute should be applied to a function definition +error: `#[rustc_lint_diagnostics]` attribute cannot be used on structs --> $DIR/diagnostics_incorrect.rs:5:1 | LL | #[rustc_lint_diagnostics] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Foo; - | ----------- not a function definition + | + = help: `#[rustc_lint_diagnostics]` can only be applied to functions + +error[E0565]: malformed `rustc_lint_diagnostics` attribute input + --> $DIR/diagnostics_incorrect.rs:10:5 + | +LL | #[rustc_lint_diagnostics(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[rustc_lint_diagnostics]` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0565`.