diff options
| author | bors <bors@rust-lang.org> | 2025-07-06 16:56:16 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-07-06 16:56:16 +0000 |
| commit | de031bbcb161b0b7fc0eb16f77b02ce9fbdf4c9e (patch) | |
| tree | 2f67f39a59825f5628e9f511f3c7e1fa6f847ab5 /compiler | |
| parent | 3c95364c4afc3f15749f5a511d599af086f5456e (diff) | |
| parent | bff79a75172b5f8200b4f30264e5fc9d36f8080e (diff) | |
| download | rust-de031bbcb161b0b7fc0eb16f77b02ce9fbdf4c9e.tar.gz rust-de031bbcb161b0b7fc0eb16f77b02ce9fbdf4c9e.zip | |
Auto merge of #143526 - matthiaskrgr:rollup-pm69g5v, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - rust-lang/rust#143252 (Rewrite empty attribute lint for new attribute parser) - rust-lang/rust#143492 (Use `object` crate from crates.io to fix windows build error) - rust-lang/rust#143514 (Organize macro tests a bit more) - rust-lang/rust#143518 (rustc_builtin_macros: Make sure registered attributes stay sorted) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
20 files changed, 96 insertions, 90 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 6af15da7d08..ba62be676d4 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -67,8 +67,6 @@ pub enum ReprAttr { ReprSimd, ReprTransparent, ReprAlign(Align), - // this one is just so we can emit a lint for it - ReprEmpty, } pub use ReprAttr::*; @@ -304,7 +302,7 @@ pub enum AttributeKind { PubTransparent(Span), /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). - Repr(ThinVec<(ReprAttr, Span)>), + Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, /// Represents `#[rustc_layout_scalar_valid_range_end]`. RustcLayoutScalarValidRangeEnd(Box<u128>, Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 8ebd38a6ba7..b109ebbf47b 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -41,7 +41,7 @@ impl AttributeKind { Optimize(..) => No, PassByValue(..) => Yes, PubTransparent(..) => Yes, - Repr(..) => No, + Repr { .. } => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcObjectLifetimeDefault => No, diff --git a/compiler/rustc_attr_data_structures/src/lints.rs b/compiler/rustc_attr_data_structures/src/lints.rs index e34c54c6d32..60ca4d43ce9 100644 --- a/compiler/rustc_attr_data_structures/src/lints.rs +++ b/compiler/rustc_attr_data_structures/src/lints.rs @@ -12,4 +12,5 @@ pub struct AttributeLint<Id> { pub enum AttributeLintKind { UnusedDuplicate { this: Span, other: Span, warning: bool }, IllFormedAttributeInput { suggestions: Vec<String> }, + EmptyAttribute { first_span: Span }, } diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 9ad46a83f50..8a709ea5d20 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -6,6 +6,10 @@ attr_parsing_deprecated_item_suggestion = .help = add `#![feature(deprecated_suggestion)]` to the crate root .note = see #94785 for more details +attr_parsing_empty_attribute = + unused attribute + .suggestion = remove this attribute + attr_parsing_empty_confusables = expected at least one confusable name attr_parsing_expected_one_cfg_pattern = diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 13f560dff38..cb3956d46a0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -298,6 +298,10 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser { cx.expected_list(cx.attr_span); return features; }; + if list.is_empty() { + cx.warn_empty_attribute(cx.attr_span); + return features; + } for item in list.mixed() { let Some(name_value) = item.meta_item() else { cx.expected_name_value(item.span(), Some(sym::enable)); diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 1c070dc2685..6a45832ed7f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -23,7 +23,8 @@ pub(crate) struct ReprParser; impl<S: Stage> CombineAttributeParser<S> for ReprParser { type Item = (ReprAttr, Span); const PATH: &[Symbol] = &[sym::repr]; - const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::Repr(items); + const CONVERT: ConvertFn<Self::Item> = + |items, first_span| AttributeKind::Repr { reprs: items, first_span }; // FIXME(jdonszelmann): never used const TEMPLATE: AttributeTemplate = template!(List: "C | Rust | align(...) | packed(...) | <integer type> | transparent"); @@ -40,8 +41,8 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser { }; if list.is_empty() { - // this is so validation can emit a lint - reprs.push((ReprAttr::ReprEmpty, cx.attr_span)); + cx.warn_empty_attribute(cx.attr_span); + return reprs; } for param in list.mixed() { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 2a01ee58493..bcd7b024a9e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -165,6 +165,7 @@ mod private { #[allow(private_interfaces)] pub trait Stage: Sized + 'static + Sealed { type Id: Copy; + const SHOULD_EMIT_LINTS: bool; fn parsers() -> &'static group_type!(Self); @@ -175,6 +176,7 @@ pub trait Stage: Sized + 'static + Sealed { #[allow(private_interfaces)] impl Stage for Early { type Id = NodeId; + const SHOULD_EMIT_LINTS: bool = false; fn parsers() -> &'static group_type!(Self) { &early::ATTRIBUTE_PARSERS @@ -188,6 +190,7 @@ impl Stage for Early { #[allow(private_interfaces)] impl Stage for Late { type Id = HirId; + const SHOULD_EMIT_LINTS: bool = true; fn parsers() -> &'static group_type!(Self) { &late::ATTRIBUTE_PARSERS @@ -228,6 +231,9 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { /// must be delayed until after HIR is built. This method will take care of the details of /// that. pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) { + if !S::SHOULD_EMIT_LINTS { + return; + } let id = self.target_id; (self.emit_lint)(AttributeLint { id, span, kind: lint }); } @@ -409,6 +415,10 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { }, }) } + + pub(crate) fn warn_empty_attribute(&mut self, span: Span) { + self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span); + } } impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> { diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs index fee22293b47..e648ca4fdf8 100644 --- a/compiler/rustc_attr_parsing/src/lints.rs +++ b/compiler/rustc_attr_parsing/src/lints.rs @@ -28,5 +28,11 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi }, ); } + AttributeLintKind::EmptyAttribute { first_span } => lint_emitter.emit_node_span_lint( + rustc_session::lint::builtin::UNUSED_ATTRIBUTES, + *id, + *first_span, + session_diagnostics::EmptyAttributeList { attr_span: *first_span }, + ), } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 6145f1e1d3e..28f6786f37f 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -473,6 +473,13 @@ pub(crate) struct EmptyConfusables { pub span: Span, } +#[derive(LintDiagnostic)] +#[diag(attr_parsing_empty_attribute)] +pub(crate) struct EmptyAttributeList { + #[suggestion(code = "", applicability = "machine-applicable")] + pub attr_span: Span, +} + #[derive(Diagnostic)] #[diag(attr_parsing_invalid_alignment_value, code = E0589)] pub(crate) struct InvalidAlignmentValue { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index d201ca196d6..8135f3744f8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -485,7 +485,7 @@ impl<'a> TraitDef<'a> { Annotatable::Item(item) => { let is_packed = matches!( AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id), - Some(Attribute::Parsed(AttributeKind::Repr(r))) if r.iter().any(|(x, _)| matches!(x, ReprPacked(..))) + Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) ); let newitem = match &item.kind { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 0594f7e86c3..6bf590df5c9 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -108,6 +108,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } register_attr! { + // tidy-alphabetical-start alloc_error_handler: alloc_error_handler::expand, autodiff_forward: autodiff::expand_forward, autodiff_reverse: autodiff::expand_reverse, @@ -120,6 +121,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, + // tidy-alphabetical-end } register_derive! { diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index b20c181a8cb..7f35c1a80bd 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -144,6 +144,15 @@ dependencies = [ ] [[package]] +name = "object" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" +dependencies = [ + "memchr", +] + +[[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -179,6 +188,7 @@ dependencies = [ "boml", "gccjit", "lang_tester", + "object", "tempfile", ] diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml index c284e3f060b..193348d1ef6 100644 --- a/compiler/rustc_codegen_gcc/Cargo.toml +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -22,6 +22,8 @@ master = ["gccjit/master"] default = ["master"] [dependencies] +object = { version = "0.37.0", default-features = false, features = ["std", "read"] } +tempfile = "3.20" gccjit = "2.7" #gccjit = { git = "https://github.com/rust-lang/gccjit.rs" } @@ -31,7 +33,6 @@ gccjit = "2.7" [dev-dependencies] boml = "0.3.1" lang_tester = "0.8.0" -tempfile = "3.20" [profile.dev] # By compiling dependencies with optimizations, performing tests gets much faster. diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a912678ef2a..1a6eec0ed0b 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -26,12 +26,9 @@ #![deny(clippy::pattern_type_mismatch)] #![allow(clippy::needless_lifetimes, clippy::uninlined_format_args)] -// Some "regular" crates we want to share with rustc -extern crate object; +// These crates are pulled from the sysroot because they are part of +// rustc's public API, so we need to ensure version compatibility. extern crate smallvec; -// FIXME(antoyo): clippy bug: remove the #[allow] when it's fixed. -#[allow(unused_extern_crates)] -extern crate tempfile; #[macro_use] extern crate tracing; diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 2713ec07f97..be63bb8ac59 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -109,7 +109,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if let hir::Attribute::Parsed(p) = attr { match p { - AttributeKind::Repr(reprs) => { + AttributeKind::Repr { reprs, first_span: _ } => { codegen_fn_attrs.alignment = reprs .iter() .filter_map( diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f4fcb13b1a1..bd89d010a3c 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1395,8 +1395,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { let repr = def.repr(); if repr.packed() { - if let Some(reprs) = - attrs::find_attr!(tcx.get_all_attrs(def.did()), attrs::AttributeKind::Repr(r) => r) + if let Some(reprs) = attrs::find_attr!(tcx.get_all_attrs(def.did()), attrs::AttributeKind::Repr { reprs, .. } => reprs) { for (r, _) in reprs { if let ReprPacked(pack) = r @@ -1619,10 +1618,10 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { if def.variants().is_empty() { attrs::find_attr!( tcx.get_all_attrs(def_id), - attrs::AttributeKind::Repr(rs) => { + attrs::AttributeKind::Repr { reprs, first_span } => { struct_span_code_err!( tcx.dcx(), - rs.first().unwrap().1, + reprs.first().map(|repr| repr.1).unwrap_or(*first_span), E0084, "unsupported representation for zero-variant enum" ) diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 97e627f2eb2..ad7686b3e5b 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -168,7 +168,7 @@ impl EarlyLintPass for NonCamelCaseTypes { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { let has_repr_c = matches!( AttributeParser::parse_limited(cx.sess(), &it.attrs, sym::repr, it.span, it.id), - Some(Attribute::Parsed(AttributeKind::Repr(r))) if r.iter().any(|(r, _)| r == &ReprAttr::ReprC) + Some(Attribute::Parsed(AttributeKind::Repr { reprs, ..})) if reprs.iter().any(|(r, _)| r == &ReprAttr::ReprC) ); if has_repr_c { diff --git a/compiler/rustc_macros/src/print_attribute.rs b/compiler/rustc_macros/src/print_attribute.rs index 42d94e72ee9..9023520c750 100644 --- a/compiler/rustc_macros/src/print_attribute.rs +++ b/compiler/rustc_macros/src/print_attribute.rs @@ -21,7 +21,8 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok __p.word_space(","); } __p.word(#string_name); - __p.word_space(":"); + __p.word(":"); + __p.nbsp(); __printed_anything = true; } #name.print_attribute(__p); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f1b16ea54e6..b780b1c5776 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1525,7 +1525,8 @@ impl<'tcx> TyCtxt<'tcx> { field_shuffle_seed ^= user_seed; } - if let Some(reprs) = attr::find_attr!(self.get_all_attrs(did), AttributeKind::Repr(r) => r) + if let Some(reprs) = + attr::find_attr!(self.get_all_attrs(did), AttributeKind::Repr { reprs, .. } => reprs) { for (r, _) in reprs { flags.insert(match *r { @@ -1566,10 +1567,6 @@ impl<'tcx> TyCtxt<'tcx> { max_align = max_align.max(Some(align)); ReprFlags::empty() } - attr::ReprEmpty => { - /* skip these, they're just for diagnostics */ - ReprFlags::empty() - } }); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 18b3ab12e2d..3fa5cdc36bc 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -160,7 +160,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } Attribute::Parsed(AttributeKind::DocComment { .. }) => { /* `#[doc]` is actually a lot more than just doc comments, so is checked below*/ } - Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */ + Attribute::Parsed(AttributeKind::Repr { .. }) => { /* handled below this loop and elsewhere */ } Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => { self.check_object_lifetime_default(hir_id); @@ -1948,7 +1948,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // #[repr(foo)] // #[repr(bar, align(8))] // ``` - let reprs = find_attr!(attrs, AttributeKind::Repr(r) => r.as_slice()).unwrap_or(&[]); + let (reprs, first_attr_span) = find_attr!(attrs, AttributeKind::Repr { reprs, first_span } => (reprs.as_slice(), Some(*first_span))).unwrap_or((&[], None)); let mut int_reprs = 0; let mut is_explicit_rust = false; @@ -2045,31 +2045,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> { continue; } } - // FIXME(jdonszelmann): move the diagnostic for unused repr attrs here, I think - // it's a better place for it. - ReprAttr::ReprEmpty => { - // catch `repr()` with no arguments, applied to an item (i.e. not `#![repr()]`) - if item.is_some() { - match target { - Target::Struct | Target::Union | Target::Enum => continue, - Target::Fn | Target::Method(_) => { - self.dcx().emit_err(errors::ReprAlignShouldBeAlign { - span: *repr_span, - item: target.name(), - }); - } - _ => { - self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { - hint_span: *repr_span, - span, - }); - } - } - } + }; + } - return; + // catch `repr()` with no arguments, applied to an item (i.e. not `#![repr()]`) + if let Some(first_attr_span) = first_attr_span + && reprs.is_empty() + && item.is_some() + { + match target { + Target::Struct | Target::Union | Target::Enum => {} + Target::Fn | Target::Method(_) => { + self.dcx().emit_err(errors::ReprAlignShouldBeAlign { + span: first_attr_span, + item: target.name(), + }); } - }; + _ => { + self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { + hint_span: first_attr_span, + span, + }); + } + } + return; } // Just point at all repr hints if there are any incompatibilities. @@ -2324,43 +2323,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute, style: Option<AttrStyle>) { - // FIXME(jdonszelmann): deduplicate these checks after more attrs are parsed. This is very - // ugly now but can 100% be removed later. - if let Attribute::Parsed(p) = attr { - match p { - AttributeKind::Repr(reprs) => { - for (r, span) in reprs { - if let ReprAttr::ReprEmpty = r { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - *span, - errors::Unused { - attr_span: *span, - note: errors::UnusedNote::EmptyList { name: sym::repr }, - }, - ); - } - } - return; - } - AttributeKind::TargetFeature(features, span) if features.len() == 0 => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - *span, - errors::Unused { - attr_span: *span, - note: errors::UnusedNote::EmptyList { name: sym::target_feature }, - }, - ); - return; - } - _ => {} - }; - } - // Warn on useless empty attributes. + // FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute` let note = if attr.has_any_name(&[ sym::macro_use, sym::allow, @@ -2576,7 +2540,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { - if !find_attr!(attrs, AttributeKind::Repr(r) => r.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent)) + if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent)) .unwrap_or(false) { self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span }); @@ -2852,8 +2816,12 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { ATTRS_TO_CHECK.iter().find(|attr_to_check| attr.has_name(**attr_to_check)) { (attr.span(), *a) - } else if let Attribute::Parsed(AttributeKind::Repr(r)) = attr { - (r.first().unwrap().1, sym::repr) + } else if let Attribute::Parsed(AttributeKind::Repr { + reprs: _, + first_span: first_attr_span, + }) = attr + { + (*first_attr_span, sym::repr) } else { continue; }; |
