diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 46c21dcf67b19..a472c52836049 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -17,6 +17,10 @@ passes_align_attr_application = `#[align(...)]` should be applied to a function item .label = not a function item +passes_align_on_fields = + attribute should be applied to a function or method + .warn = {-passes_previously_accepted} + passes_align_should_be_repr_align = `#[align(...)]` is not supported on {$item} items .suggestion = use `#[repr(align(...))]` instead diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 86f10f335893a..9aab31955392e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -43,6 +43,7 @@ use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; +use crate::errors::AlignOnFields; use crate::{errors, fluent_generated as fluent}; #[derive(LintDiagnostic)] @@ -197,8 +198,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => { self.check_export_name(hir_id, *attr_span, span, target) } - Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { - self.check_align(span, target, *align, *repr_span) + Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => { + self.check_align(span, hir_id, target, *align, *attr_span) } Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => { self.check_link_section(hir_id, *attr_span, span, target) @@ -1933,22 +1934,37 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if the `#[align]` attributes on `item` are valid. - fn check_align(&self, span: Span, target: Target, align: Align, repr_span: Span) { + fn check_align( + &self, + span: Span, + hir_id: HirId, + target: Target, + align: Align, + attr_span: Span, + ) { match target { Target::Fn | Target::Method(_) | Target::ForeignFn => {} + Target::Field => { + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr_span, + AlignOnFields { span }, + ); + } Target::Struct | Target::Union | Target::Enum => { self.dcx().emit_err(errors::AlignShouldBeReprAlign { - span: repr_span, + span: attr_span, item: target.name(), align_bytes: align.bytes(), }); } _ => { - self.dcx().emit_err(errors::AlignAttrApplication { hint_span: repr_span, span }); + self.dcx().emit_err(errors::AlignAttrApplication { hint_span: attr_span, span }); } } - self.check_align_value(align, repr_span); + self.check_align_value(align, attr_span); } /// Checks if the `#[repr]` attributes on `item` are valid. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4ad615a2abfc8..093a2b38804fd 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -604,6 +604,14 @@ pub(crate) struct NoMangle { pub span: Span, } +#[derive(LintDiagnostic)] +#[diag(passes_align_on_fields)] +#[warning] +pub(crate) struct AlignOnFields { + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_repr_conflicting, code = E0566)] pub(crate) struct ReprConflicting {