diff options
| author | Trevor Gross <t.gross35@gmail.com> | 2025-06-18 20:22:49 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-18 20:22:49 -0400 |
| commit | 07932ad11153b62ec2138fa71a398a1ca8ea05ac (patch) | |
| tree | 289f0c510ce9d472d6c5e29424f3174fe7ac71b9 /compiler | |
| parent | cff8e9ae142c3dcaf4c66ec5b6be932f1442c4b5 (diff) | |
| parent | 1fdf2b562070ec98c5b32ee67b8c6d8145127a6e (diff) | |
| download | rust-07932ad11153b62ec2138fa71a398a1ca8ea05ac.tar.gz rust-07932ad11153b62ec2138fa71a398a1ca8ea05ac.zip | |
Rollup merge of #142507 - folkertdev:fn-align-align-attribute, r=jdonszelmann
use `#[align]` attribute for `fn_align` Tracking issue: https://github.com/rust-lang/rust/issues/82232 https://github.com/rust-lang/rfcs/pull/3806 decides to add the `#[align]` attribute for alignment of various items. Right now it's used for functions with `fn_align`, in the future it will get more uses (statics, struct fields, etc.) (the RFC finishes FCP today) r? `@ghost`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_attr_data_structures/src/attributes.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/attributes/repr.rs | 58 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/context.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/session_diagnostics.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/builtin_attrs.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/middle/codegen_fn_attrs.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/validate_attr.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_passes/messages.ftl | 15 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 75 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 30 |
12 files changed, 154 insertions, 60 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d4c43456049..cdc01dc6c91 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -182,6 +182,9 @@ impl Deprecation { #[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] pub enum AttributeKind { // tidy-alphabetical-start + /// Represents `#[align(N)]`. + Align { align: Align, span: Span }, + /// Represents `#[rustc_allow_const_fn_unstable]`. AllowConstFnUnstable(ThinVec<Symbol>), diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index b9b386635f6..0891afc003e 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -44,6 +44,9 @@ attr_parsing_incorrect_repr_format_packed_expect_integer = attr_parsing_incorrect_repr_format_packed_one_or_zero_arg = incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all +attr_parsing_invalid_alignment_value = + invalid alignment value: {$error_part} + attr_parsing_invalid_issue_string = `issue` must be a non-zero numeric string or "none" .must_not_be_zero = `issue` must not be "0", use "none" instead diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index ae9e7871874..c9f9f34bdb7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -4,7 +4,7 @@ use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr}; use rustc_feature::{AttributeTemplate, template}; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; -use super::{CombineAttributeParser, ConvertFn}; +use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext}; use crate::context::{AcceptContext, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser}; use crate::session_diagnostics; @@ -203,7 +203,7 @@ fn parse_repr_align<S: Stage>( }); } Align => { - cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { + cx.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { span: param_span, }); } @@ -266,3 +266,57 @@ fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> { Err("not an unsuffixed integer") } } + +/// Parse #[align(N)]. +#[derive(Default)] +pub(crate) struct AlignParser(Option<(Align, Span)>); + +impl AlignParser { + const PATH: &'static [Symbol] = &[sym::align]; + const TEMPLATE: AttributeTemplate = template!(Word, List: "<alignment in bytes>"); + + fn parse<'c, S: Stage>( + &mut self, + cx: &'c mut AcceptContext<'_, '_, S>, + args: &'c ArgParser<'_>, + ) { + match args { + ArgParser::NoArgs | ArgParser::NameValue(_) => { + cx.expected_list(cx.attr_span); + } + ArgParser::List(list) => { + let Some(align) = list.single() else { + cx.expected_single_argument(list.span); + return; + }; + + let Some(lit) = align.lit() else { + cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger { + span: align.span(), + }); + + return; + }; + + match parse_alignment(&lit.kind) { + Ok(literal) => self.0 = Ord::max(self.0, Some((literal, cx.attr_span))), + Err(message) => { + cx.emit_err(session_diagnostics::InvalidAlignmentValue { + span: lit.span, + error_part: message, + }); + } + } + } + } + } +} + +impl<S: Stage> AttributeParser<S> for AlignParser { + const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; + + fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { + let (align, span) = self.0?; + Some(AttributeKind::Align { align, span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 51c1760da30..d7570634c1f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -19,7 +19,7 @@ use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::lint_helpers::AsPtrParser; -use crate::attributes::repr::ReprParser; +use crate::attributes::repr::{AlignParser, ReprParser}; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; @@ -90,6 +90,7 @@ macro_rules! attribute_parsers { attribute_parsers!( pub(crate) static ATTRIBUTE_PARSERS = [ // tidy-alphabetical-start + AlignParser, BodyStabilityParser, ConfusablesParser, ConstStabilityParser, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 57ac92a0ca1..337921a318c 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -451,6 +451,14 @@ pub(crate) struct EmptyConfusables { } #[derive(Diagnostic)] +#[diag(attr_parsing_invalid_alignment_value, code = E0589)] +pub(crate) struct InvalidAlignmentValue { + #[primary_span] + pub span: Span, + pub error_part: &'static str, +} + +#[derive(Diagnostic)] #[diag(attr_parsing_repr_ident, code = E0565)] pub(crate) struct ReprIdent { #[primary_span] diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 188a9a98ce7..98742255063 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use rustc_abi::ExternAbi; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; -use rustc_attr_data_structures::ReprAttr::ReprAlign; use rustc_attr_data_structures::{ AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, find_attr, }; @@ -110,17 +109,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } }; - if let hir::Attribute::Parsed(p) = attr { - match p { - AttributeKind::Repr(reprs) => { - codegen_fn_attrs.alignment = reprs - .iter() - .filter_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None }) - .max(); - } - - _ => {} - } + if let hir::Attribute::Parsed(AttributeKind::Align { align, .. }) = attr { + codegen_fn_attrs.alignment = Some(*align); } let Some(Ident { name, .. }) = attr.ident() else { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index b5218ec267c..5b1f1684d54 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -495,6 +495,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No), + gated!(align, Normal, template!(List: "alignment"), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(align)), ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index f21cf5fa45e..2f16d385efb 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -47,8 +47,7 @@ pub struct CodegenFnAttrs { /// be generated against a specific instruction set. Only usable on architectures which allow /// switching between multiple instruction sets. pub instruction_set: Option<InstructionSetAttr>, - /// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be - /// aligned to. + /// The `#[align(...)]` attribute. Determines the alignment of the function body. pub alignment: Option<Align>, /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around /// the function entry. diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index b3096e46b09..a12215a44f9 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -289,6 +289,7 @@ fn emit_malformed_attribute( | sym::rustc_force_inline | sym::rustc_confusables | sym::repr + | sym::align | sym::deprecated ) { return; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 7c237d708c0..c1a2b3b2973 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -13,6 +13,10 @@ passes_abi_ne = passes_abi_of = fn_abi_of({$fn_name}) = {$fn_abi} +passes_align_should_be_repr_align = + `#[align(...)]` is not supported on {$item} items + .suggestion = use `#[repr(align(...))]` instead + passes_allow_incoherent_impl = `rustc_allow_incoherent_impl` attribute should be applied to impl items .label = the only currently supported targets are inherent methods @@ -29,10 +33,6 @@ passes_attr_application_struct = attribute should be applied to a struct .label = not a struct -passes_attr_application_struct_enum_function_method_union = - attribute should be applied to a struct, enum, function, associated function, or union - .label = not a struct, enum, function, associated function, or union - passes_attr_application_struct_enum_union = attribute should be applied to a struct, enum, or union .label = not a struct, enum, or union @@ -583,13 +583,14 @@ passes_remove_fields = *[other] fields } -passes_repr_align_function = - `repr(align)` attributes on functions are unstable - passes_repr_align_greater_than_target_max = alignment must not be greater than `isize::MAX` bytes .note = `isize::MAX` is {$size} for the current target +passes_repr_align_should_be_align = + `#[repr(align(...))]` is not supported on {$item} items + .help = use `#[align(...)]` instead + passes_repr_conflicting = conflicting representation hints diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5ce803aa1f8..50d6c5d9764 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -146,6 +146,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */ } + Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { + self.check_align(span, target, *align, *repr_span) + } + Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect @@ -643,6 +647,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::naked, sym::instruction_set, sym::repr, + sym::align, sym::rustc_std_internal_symbol, // code generation sym::cold, @@ -679,7 +684,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // this check can be part of the parser and be removed here match other_attr { Attribute::Parsed( - AttributeKind::Deprecation { .. } | AttributeKind::Repr { .. }, + AttributeKind::Deprecation { .. } + | AttributeKind::Repr { .. } + | AttributeKind::Align { .. }, ) => { continue; } @@ -1964,6 +1971,28 @@ 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) { + match target { + Target::Fn | Target::Method(_) => {} + Target::Struct | Target::Union | Target::Enum => { + self.dcx().emit_err(errors::AlignShouldBeReprAlign { + span: repr_span, + item: target.name(), + align_bytes: align.bytes(), + }); + } + _ => { + self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { + hint_span: repr_span, + span, + }); + } + } + + self.check_align_value(align, repr_span); + } + /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, @@ -2016,23 +2045,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Struct | Target::Union | Target::Enum => {} Target::Fn | Target::Method(_) => { - if !self.tcx.features().fn_align() { - feature_err( - &self.tcx.sess, - sym::fn_align, - *repr_span, - fluent::passes_repr_align_function, - ) - .emit(); - } + self.dcx().emit_err(errors::ReprAlignShouldBeAlign { + span: *repr_span, + item: target.name(), + }); } _ => { - self.dcx().emit_err( - errors::AttrApplication::StructEnumFunctionMethodUnion { - hint_span: *repr_span, - span, - }, - ); + self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { + hint_span: *repr_span, + span, + }); } } @@ -2090,21 +2112,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Struct | Target::Union | Target::Enum => continue, Target::Fn | Target::Method(_) => { - feature_err( - &self.tcx.sess, - sym::fn_align, - *repr_span, - fluent::passes_repr_align_function, - ) - .emit(); + self.dcx().emit_err(errors::ReprAlignShouldBeAlign { + span: *repr_span, + item: target.name(), + }); } _ => { - self.dcx().emit_err( - errors::AttrApplication::StructEnumFunctionMethodUnion { - hint_span: *repr_span, - span, - }, - ); + self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { + hint_span: *repr_span, + span, + }); } } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f0d4b610f63..587d9170f06 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1308,13 +1308,6 @@ pub(crate) enum AttrApplication { #[label] span: Span, }, - #[diag(passes_attr_application_struct_enum_function_method_union, code = E0517)] - StructEnumFunctionMethodUnion { - #[primary_span] - hint_span: Span, - #[label] - span: Span, - }, } #[derive(Diagnostic)] @@ -1816,3 +1809,26 @@ pub(crate) enum UnexportableItem<'a> { field_name: &'a str, }, } + +#[derive(Diagnostic)] +#[diag(passes_repr_align_should_be_align)] +pub(crate) struct ReprAlignShouldBeAlign { + #[primary_span] + #[help] + pub span: Span, + pub item: &'static str, +} + +#[derive(Diagnostic)] +#[diag(passes_align_should_be_repr_align)] +pub(crate) struct AlignShouldBeReprAlign { + #[primary_span] + #[suggestion( + style = "verbose", + applicability = "machine-applicable", + code = "#[repr(align({align_bytes}))]" + )] + pub span: Span, + pub item: &'static str, + pub align_bytes: u64, +} |
