From 26d2c3068254f2ed31eca7eb36a1524aea4ad93e Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:00:45 +0200 Subject: [PATCH] Move diagnostic::on_move target check --- .../src/attributes/diagnostic/on_move.rs | 14 ++++++++++ compiler/rustc_attr_parsing/src/errors.rs | 4 +++ compiler/rustc_passes/src/check_attr.rs | 27 +++---------------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs index 2b62ab7f3d11..feb48fa868d4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/on_move.rs @@ -1,10 +1,13 @@ +use rustc_errors::Diagnostic; use rustc_feature::template; use rustc_hir::attrs::AttributeKind; +use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::sym; use crate::attributes::diagnostic::*; use crate::attributes::prelude::*; use crate::context::{AcceptContext, Stage}; +use crate::errors::DiagnosticOnMoveOnlyForAdt; use crate::parser::ArgParser; use crate::target_checking::{ALL_TARGETS, AllowedTargets}; @@ -29,6 +32,15 @@ fn parse<'sess, S: Stage>( let span = cx.attr_span; self.span = Some(span); + if !matches!(cx.target, Target::Enum | Target::Struct | Target::Union) { + cx.emit_dyn_lint( + MISPLACED_DIAGNOSTIC_ATTRIBUTES, + move |dcx, level| DiagnosticOnMoveOnlyForAdt.into_diag(dcx, level), + span, + ); + return; + } + let Some(items) = parse_list(cx, args, mode) else { return }; if let Some(directive) = parse_directive_items(cx, mode, items.mixed(), true) { @@ -44,6 +56,8 @@ impl AttributeParser for OnMoveParser { this.parse(cx, args, Mode::DiagnosticOnMove); }, )]; + + // "Allowed" for all targets but noop if used on not-adt. const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 8e1050852181..89ebbcae3507 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -259,3 +259,7 @@ pub(crate) struct DiagnosticOnConstOnlyForTraitImpls { #[label("not a trait impl")] pub target_span: Span, } + +#[derive(Diagnostic)] +#[diag("`#[diagnostic::on_move]` can only be applied to enums, structs or unions")] +pub(crate) struct DiagnosticOnMoveOnlyForAdt; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ecc83628971c..bd794d2d00f7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -61,10 +61,6 @@ struct DiagnosticOnConstOnlyForNonConstTraitImpls { item_span: Span, } -#[derive(Diagnostic)] -#[diag("`#[diagnostic::on_move]` can only be applied to enums, structs or unions")] -struct DiagnosticOnMoveOnlyForAdt; - #[derive(Diagnostic)] #[diag("`#[diagnostic::on_unknown]` can only be applied to `use` statements")] struct DiagnosticOnUnknownOnlyForImports { @@ -218,8 +214,8 @@ fn check_attributes( Attribute::Parsed(AttributeKind::OnUnimplemented{span, directive}) => {self.check_diagnostic_on_unimplemented(*span, hir_id, target,directive.as_deref())}, Attribute::Parsed(AttributeKind::OnUnknown { span, .. }) => { self.check_diagnostic_on_unknown(*span, hir_id, target) }, Attribute::Parsed(AttributeKind::OnConst{span, ..}) => {self.check_diagnostic_on_const(*span, hir_id, target, item)} - Attribute::Parsed(AttributeKind::OnMove { span, directive }) => { - self.check_diagnostic_on_move(*span, hir_id, target, directive.as_deref()) + Attribute::Parsed(AttributeKind::OnMove { directive , .. }) => { + self.check_diagnostic_on_move(hir_id, directive.as_deref()) }, Attribute::Parsed( // tidy-alphabetical-start @@ -613,23 +609,8 @@ fn check_diagnostic_on_const( // ...whose generics would that be, anyway? The traits' or the impls'? } - /// Checks if `#[diagnostic::on_move]` is applied to an ADT definition - fn check_diagnostic_on_move( - &self, - attr_span: Span, - hir_id: HirId, - target: Target, - directive: Option<&Directive>, - ) { - if !matches!(target, Target::Enum | Target::Struct | Target::Union) { - self.tcx.emit_node_span_lint( - MISPLACED_DIAGNOSTIC_ATTRIBUTES, - hir_id, - attr_span, - DiagnosticOnMoveOnlyForAdt, - ); - } - + /// Checks use of generic formatting parameters in `#[diagnostic::on_move]` + fn check_diagnostic_on_move(&self, hir_id: HirId, directive: Option<&Directive>) { if let Some(directive) = directive { if let Node::Item(Item { kind: