From b32b841ddbdf59d858ffd4f75ecf01a06c9dc98c Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:06:03 +0100 Subject: [PATCH 01/16] lint against repeated repr attributes --- compiler/rustc_lint_defs/src/builtin.rs | 15 +++++++++ compiler/rustc_passes/src/check_attr.rs | 43 +++++++++++++++++++++--- compiler/rustc_passes/src/diagnostics.rs | 5 +++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index d7339d1b60269..af517fbd8f4d0 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -277,6 +277,21 @@ declare_lint! { }; } +declare_lint! { + /// Todo: explain this. + /// + /// ### Example + /// + /// TODO + /// + /// ### Explanation + /// + /// TODO + pub REPEATED_REPRS, + Warn, + "repeated `#[repr(..)]` attributes were inconsistently rejected before", +} + declare_lint! { /// The `meta_variable_misuse` lint detects possible meta-variable misuse /// in macro definitions. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7f9e4fc553455..5aeb1b3ec2a02 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -30,7 +30,8 @@ use rustc_hir::{ }; use rustc_lint_defs::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES, - MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, + MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, REPEATED_REPRS, + UNUSED_ATTRIBUTES, }; use rustc_macros::Diagnostic; use rustc_middle::hir::nested_filter; @@ -1212,21 +1213,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let mut is_c = false; let mut is_simd = false; let mut is_transparent = false; + let mut is_align = false; + let mut is_packed = false; + let mut repeated_repr = false; for (repr, _repr_span) in reprs { match repr { ReprAttr::ReprRust => { + if is_explicit_rust { + repeated_repr = true + } is_explicit_rust = true; } ReprAttr::ReprC => { + if is_c { + repeated_repr = true; + } is_c = true; } - ReprAttr::ReprAlign(..) => {} - ReprAttr::ReprPacked(_) => {} + ReprAttr::ReprAlign(..) => { + if is_align { + repeated_repr = true; + } + is_align = true; + } + ReprAttr::ReprPacked(..) => { + if is_packed { + repeated_repr = true; + } + is_packed = true; + } ReprAttr::ReprSimd => { + if is_simd { + repeated_repr = true; + } is_simd = true; } ReprAttr::ReprTransparent => { + if is_transparent { + repeated_repr = true; + } is_transparent = true; } ReprAttr::ReprInt(_) => { @@ -1270,10 +1296,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( CONFLICTING_REPR_HINTS, hir_id, - hint_spans.collect::>(), + hint_spans.clone().collect::>(), diagnostics::ReprConflictingLint, ); } + + if repeated_repr { + self.tcx.emit_node_span_lint( + REPEATED_REPRS, + hir_id, + hint_spans.collect::>(), + diagnostics::RepeatedRepr, + ); + } } /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 9864e9debf9d8..deae750ca2688 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -607,6 +607,11 @@ pub(crate) struct TransparentIncompatible { pub target: String, } +#[derive(Diagnostic)] +#[diag("attribute is specified more than once")] +#[note("will become a hard error soon. todo: wording")] +pub(crate) struct RepeatedRepr; + #[derive(Diagnostic)] #[diag("deprecated attribute must be paired with either stable or unstable attribute", code = E0549)] pub(crate) struct DeprecatedAttribute { From a2f14600afb23bbebe83c167f30927a93d0fa195 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Mon, 24 Aug 2026 14:52:00 +0100 Subject: [PATCH 02/16] Fix broken link to lang_items.rs in unstable book The file path was changed in af4c79b260276522887dee7605e8ff24263bfc9a. Fix the link, and use a specific commit so it doesn't break accidentally future. --- src/doc/unstable-book/src/language-features/lang-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index deb7fbca716c3..ccc973d013e44 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -112,4 +112,4 @@ return a valid pointer, and so needs to do the check internally. An up-to-date list of all language items can be found [here] in the compiler code. -[here]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_hir/src/lang_items.rs +[here]: https://github.com/rust-lang/rust/blob/ac62df9b49f9b9036af2a4957db70bf3850785e1/compiler/rustc_attr_ir/src/lang_items.rs#L158 From dcf82c14e59c82201f65996f8524b1ebf0f07304 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 14:35:34 +1000 Subject: [PATCH 03/16] Add test demonstrating a wasm32-unknown-unknown target feature/cfg bug Due to some bad ordering of session/config initialization code -- more about that in subsequent commits -- `cfg(target_has_threads)` fails to be set for the `wasm32-unknown-unknown` platform when `-Ctarget-feature=+atomics` is specified. This commit modifies a test to demonstrate the bug; as written the test passes. --- tests/run-make/print-cfg/rmake.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs index b516bb1508ec4..09373bb480059 100644 --- a/tests/run-make/print-cfg/rmake.rs +++ b/tests/run-make/print-cfg/rmake.rs @@ -6,7 +6,7 @@ //! It also checks that some targets have the correct set cfgs. // ignore-tidy-linelength -//@ needs-llvm-components: arm x86 +//@ needs-llvm-components: arm x86 webassembly // Note: without the needs-llvm-components it will fail on LLVM built without the required // components listed above. @@ -18,6 +18,7 @@ use run_make_support::{rfs, rustc}; struct PrintCfg { target: &'static str, + args: &'static [&'static str], includes: &'static [&'static str], disallow: &'static [&'static str], } @@ -25,38 +26,57 @@ struct PrintCfg { fn main() { check(PrintCfg { target: "x86_64-pc-windows-gnu", + args: &[], includes: &["windows", "target_arch=\"x86_64\""], disallow: &["unix"], }); check(PrintCfg { target: "i686-pc-windows-msvc", + args: &[], includes: &["windows", "target_env=\"msvc\""], disallow: &["unix"], }); check(PrintCfg { target: "i686-apple-darwin", + args: &[], includes: &["unix", "target_os=\"macos\"", "target_vendor=\"apple\""], disallow: &["windows"], }); check(PrintCfg { target: "i686-unknown-linux-gnu", + args: &[], includes: &["unix", "target_env=\"gnu\""], disallow: &["windows"], }); check(PrintCfg { target: "arm-unknown-linux-gnueabihf", + args: &[], includes: &["unix", "target_abi=\"eabihf\""], disallow: &["windows"], }); // Regression test for #90834: Android must not have `target_env="gnu"`. check(PrintCfg { target: "i686-linux-android", + args: &[], includes: &["unix", "target_os=\"android\""], disallow: &["windows", "target_env=\"gnu\""], }); + check(PrintCfg { + target: "wasm32-unknown-unknown", + args: &[], + includes: &[], + disallow: &["target_has_threads"], + }); + // FIXME: `target_has_threads` is not set; it should be. + check(PrintCfg { + target: "wasm32-unknown-unknown", + args: &["-Ctarget-feature=+atomics"], + includes: &[], + disallow: &["target_has_threads"], + }); } -fn check(PrintCfg { target, includes, disallow }: PrintCfg) { +fn check(PrintCfg { target, args, includes, disallow }: PrintCfg) { fn check_(output: &str, includes: &[&str], disallow: &[&str]) { let mut found = HashSet::::new(); let mut recorded = HashSet::::new(); @@ -92,7 +112,7 @@ fn check(PrintCfg { target, includes, disallow }: PrintCfg) { // --print=cfg { - let output = rustc().target(target).print("cfg").run(); + let output = rustc().target(target).args(args).print("cfg").run(); let stdout = output.stdout_utf8(); check_(&stdout, includes, disallow); @@ -102,7 +122,7 @@ fn check(PrintCfg { target, includes, disallow }: PrintCfg) { { let tmp_path = PathBuf::from(format!("{target}.cfg")); - rustc().target(target).print(&format!("cfg={}", tmp_path.display())).run(); + rustc().target(target).args(args).print(&format!("cfg={}", tmp_path.display())).run(); let output = rfs::read_to_string(&tmp_path); From e45b83a3446af548dd2e08e7cf2d2f73b6c4baee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 11:24:24 +1000 Subject: [PATCH 04/16] Do more in `parse_cfg`/`parse_check_cfg` - `parse_check_cfg` has a single call site and is followed by a call to `fill_well_known`. - `parse_cfg` has two call sites and in both cases is followed by a call to `build_configuration`. This commit moves the follow-up calls into the functions, simplifying `run_compiler`. --- compiler/rustc_interface/src/interface.rs | 28 +++++++++++++---------- compiler/rustc_interface/src/tests.rs | 5 ++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 59f49ddc2f6e0..6ae056edc3f2d 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -44,8 +44,9 @@ pub struct Compiler { } /// Converts strings provided as `--cfg [cfgspec]` into a `Cfg`. -pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { - cfgs.into_iter() +pub(crate) fn parse_cfg(sess: &Session, cfgs: Vec) -> Cfg { + let cfg = cfgs + .into_iter() .map(|s| { let psess = ParseSess::emitter_with_note(format!( "this occurred on the command line: `--cfg={s}`" @@ -54,7 +55,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { macro_rules! error { ($reason: expr) => { - dcx.fatal(format!("invalid `--cfg` argument: `{s}` ({})", $reason)); + sess.dcx().fatal(format!("invalid `--cfg` argument: `{s}` ({})", $reason)); }; } @@ -106,11 +107,13 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { error!(r#"expected `key` or `key="value"`"#); } }) - .collect::() + .collect::(); + + config::build_configuration(sess, cfg) } /// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. -pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> CheckCfg { +pub(crate) fn parse_check_cfg(sess: &Session, specs: Vec) -> CheckCfg { // If any --check-cfg is passed then exhaustive_values and exhaustive_names // are enabled by default. let exhaustive_names = !specs.is_empty(); @@ -128,13 +131,15 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch macro_rules! error { ($reason:expr) => {{ - let mut diag = dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); + let mut diag = + sess.dcx().struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); diag.note($reason); diag.note(VISIT); diag.emit() }}; (in $arg:expr, $reason:expr) => {{ - let mut diag = dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); + let mut diag = + sess.dcx().struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg); if let Some(lit) = $arg.lit() { @@ -304,6 +309,8 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch } } + check_cfg.fill_well_known(&sess.target); + check_cfg } @@ -443,14 +450,11 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se sess.fallback_intrinsics = FxHashSet::from_iter(codegen_backend.fallback_intrinsics()); sess.thin_lto_supported = codegen_backend.thin_lto_supported(); - let cfg = parse_cfg(sess.dcx(), config.crate_cfg); - let mut cfg = config::build_configuration(&sess, cfg); + let mut cfg = parse_cfg(&sess, config.crate_cfg); util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); sess.config = cfg; - let mut check_cfg = parse_check_cfg(sess.dcx(), config.crate_check_cfg); - check_cfg.fill_well_known(&sess.target); - sess.check_config = check_cfg; + sess.check_config = parse_check_cfg(&sess, config.crate_check_cfg); if let Some(psess_created) = config.psess_created { psess_created(&mut sess.psess); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 15d7a1609c67f..d3c479f2a22f5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -17,7 +17,7 @@ use rustc_session::config::{ LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, - WasiExecModel, build_configuration, build_session_options, rustc_optgroups, + WasiExecModel, build_session_options, rustc_optgroups, }; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib}; @@ -75,8 +75,7 @@ where None, &USING_INTERNAL_FEATURES, ); - let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg")); - let cfg = build_configuration(&sess, cfg); + let cfg = parse_cfg(&sess, matches.opt_strs("cfg")); f(sess, cfg) }); } From 45c4d9cbf9711a28244094b6b7572ee659fd05c7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 11:45:43 +1000 Subject: [PATCH 05/16] Simplify `add_configuration` Currently it modifies the `Session` and the `Cfg` (and the `Cfg` afterwards is put into the `Session`). It also takes a `CodegenBackend`. Those are some heavyweight arguments. This commit moves the `Session` modifications to the caller so the `&mut Session` isn't necessary, and passes in the `TargetConfig` instead of the whole `CodegenBackend`, plus some other small arguments. `add_configuration` ends up more clearly about modifying the `Cfg`. This is a step towards untangling session/backend initialization. --- compiler/rustc_interface/src/interface.rs | 19 ++++++++++--- compiler/rustc_interface/src/util.rs | 33 ++++++++++------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 6ae056edc3f2d..1e8554b6ebe43 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -450,9 +450,22 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se sess.fallback_intrinsics = FxHashSet::from_iter(codegen_backend.fallback_intrinsics()); sess.thin_lto_supported = codegen_backend.thin_lto_supported(); - let mut cfg = parse_cfg(&sess, config.crate_cfg); - util::add_configuration(&mut cfg, &mut sess, &*codegen_backend); - sess.config = cfg; + let target_config = codegen_backend.target_config(&sess); + + sess.config = parse_cfg(&sess, config.crate_cfg); + let is_nightly_build = sess.is_nightly_build(); + let is_crt_static = sess.crt_static(None); + util::add_configuration( + &mut sess.config, + &target_config, + &sess.target, + is_nightly_build, + is_crt_static, + ); + + // Store all of the target features in the session. + sess.internal_target_features + .extend(target_config.internal_target_features.into_sorted_stable_ord()); sess.check_config = parse_check_cfg(&sess, config.crate_check_cfg); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 89907447571ee..1af2094c93d0d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -42,52 +42,47 @@ type MakeBackendFn = fn() -> Box; /// specific features (SSE, NEON etc.). /// /// This is performed by checking whether a set of permitted features -/// is available on the target machine, by querying the codegen backend. +/// is available on the target machine, by querying the `TargetConfig` from the codegen backend. pub(crate) fn add_configuration( cfg: &mut Cfg, - sess: &mut Session, - codegen_backend: &dyn CodegenBackend, + target_config: &TargetConfig, + target: &Target, + is_nightly_build: bool, + is_crt_static: bool, ) { - let tf = sym::target_feature; - let tf_cfg = codegen_backend.target_config(sess); - // Add some of the target features to `cfg`. cfg.extend( - sess.target + target .rust_target_features() .iter() .filter_map(|(feature, gate, _)| { if gate.in_cfg() - && (sess.is_nightly_build() - || gate.requires_nightly(/* in_cfg */ true).is_none()) + && (is_nightly_build || gate.requires_nightly(/* in_cfg */ true).is_none()) { Some(Symbol::intern(feature)) } else { None } }) - .filter(|feature| tf_cfg.internal_target_features.contains(&feature)) + .filter(|feature| target_config.internal_target_features.contains(&feature)) .map(|feature| (sym::target_feature, Some(feature))), ); - // Store all of them in the session. - sess.internal_target_features.extend(tf_cfg.internal_target_features.into_sorted_stable_ord()); - - if tf_cfg.has_reliable_f16 { + if target_config.has_reliable_f16 { cfg.insert((sym::target_has_reliable_f16, None)); } - if tf_cfg.has_reliable_f16_math { + if target_config.has_reliable_f16_math { cfg.insert((sym::target_has_reliable_f16_math, None)); } - if tf_cfg.has_reliable_f128 { + if target_config.has_reliable_f128 { cfg.insert((sym::target_has_reliable_f128, None)); } - if tf_cfg.has_reliable_f128_math { + if target_config.has_reliable_f128_math { cfg.insert((sym::target_has_reliable_f128_math, None)); } - if sess.crt_static(None) { - cfg.insert((tf, Some(sym::crt_dash_static))); + if is_crt_static { + cfg.insert((sym::target_feature, Some(sym::crt_dash_static))); } } From 62578dfddea950705da9ea1d72533ce79af0e623 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 13:58:13 +1000 Subject: [PATCH 06/16] Fix the wasm32-unknown-unknown target feature/cfg bug Currently, `parse_cfg` calls `build_configuration`, which calls `default_configuration`, which calls `sess.target.singlethread(&sess.internal_target_features)`. But `sess.internal_target_features` hasn't been set at this point and is empty! This commit moves the setting of `sess.internal_target_features` before the `parse_cfg` call to fix this ordering bug. This results in the `cfg(target_has_threads)` being correctly set on `wasm32-unknown-unknown` when `-Ctarget-feature=+atomics` is specified. Note: I have plans to make this kind of ordering bug difficult/impossible in a follow-up (e.g. #161432). --- compiler/rustc_interface/src/interface.rs | 9 +++++---- tests/run-make/print-cfg/rmake.rs | 5 ++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 1e8554b6ebe43..da1f7d2a33967 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -452,6 +452,11 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let target_config = codegen_backend.target_config(&sess); + // Store all of the target features in the session. + // Needs to be done before `parse_cfg` because it checks this list. + sess.internal_target_features + .extend(target_config.internal_target_features.to_sorted_stable_ord()); + sess.config = parse_cfg(&sess, config.crate_cfg); let is_nightly_build = sess.is_nightly_build(); let is_crt_static = sess.crt_static(None); @@ -463,10 +468,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se is_crt_static, ); - // Store all of the target features in the session. - sess.internal_target_features - .extend(target_config.internal_target_features.into_sorted_stable_ord()); - sess.check_config = parse_check_cfg(&sess, config.crate_check_cfg); if let Some(psess_created) = config.psess_created { diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs index 09373bb480059..d5de89c0de151 100644 --- a/tests/run-make/print-cfg/rmake.rs +++ b/tests/run-make/print-cfg/rmake.rs @@ -67,12 +67,11 @@ fn main() { includes: &[], disallow: &["target_has_threads"], }); - // FIXME: `target_has_threads` is not set; it should be. check(PrintCfg { target: "wasm32-unknown-unknown", args: &["-Ctarget-feature=+atomics"], - includes: &[], - disallow: &["target_has_threads"], + includes: &["target_has_threads"], + disallow: &[], }); } From ad2aa1ccb2046471f9c869a5e974b40a90435739 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 21:39:59 +1000 Subject: [PATCH 07/16] Remove `RawDefPathHash` `RawSpan`, `RawDefId`, and `RawDefPathHash` were all introduced to work around the fact that `StableHashCtxt` in `rustc_data_structure` is upstream of `rustc_span`. However, `DefPathHash` is just a newtype around `Fingerprint`, which is defined in `rustc_data_structure`. So by working directly with `Fingerprint` we can remove `RawDefPathHash`, which is a nice simplification. --- compiler/rustc_data_structures/src/stable_hash.rs | 10 ++++------ .../rustc_data_structures/src/stable_hash/tests.rs | 2 +- compiler/rustc_middle/src/ich.rs | 7 ++++--- compiler/rustc_span/src/def_id.rs | 14 ++------------ 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hash.rs b/compiler/rustc_data_structures/src/stable_hash.rs index 26090fdb26754..0513c90831c8c 100644 --- a/compiler/rustc_data_structures/src/stable_hash.rs +++ b/compiler/rustc_data_structures/src/stable_hash.rs @@ -8,6 +8,8 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use smallvec::SmallVec; use thin_vec::ThinVec; +use crate::fingerprint::Fingerprint; + #[cfg(test)] mod tests; @@ -24,8 +26,8 @@ pub trait StableHashCtxt { /// The main event: stable hashing of a span. fn stable_hash_span(&mut self, span: RawSpan, hasher: &mut StableHasher); - /// Compute a `DefPathHash`. - fn def_path_hash(&self, def_id: RawDefId) -> RawDefPathHash; + /// Compute a `Fingerprint`, which can be trivially turned into a `DefPathHash`. + fn def_path_hash(&self, def_id: RawDefId) -> Fingerprint; /// Get the stable hash controls. fn stable_hash_controls(&self) -> StableHashControls; @@ -43,10 +45,6 @@ pub struct RawSpan(pub u32, pub u16, pub u16); // `DefId`. pub struct RawDefId(pub u32, pub u32); -// A type used to work around `DefPathHash` not being visible in this crate. It is the same size as -// `DefPathHash`. -pub struct RawDefPathHash(pub [u8; 16]); - /// Something that implements `StableHash` can be hashed in a way that is /// stable across multiple compilation sessions. /// diff --git a/compiler/rustc_data_structures/src/stable_hash/tests.rs b/compiler/rustc_data_structures/src/stable_hash/tests.rs index 21c23e93fb022..163e441d5a47d 100644 --- a/compiler/rustc_data_structures/src/stable_hash/tests.rs +++ b/compiler/rustc_data_structures/src/stable_hash/tests.rs @@ -11,7 +11,7 @@ impl StableHashCtxt for () { fn stable_hash_span(&mut self, _: RawSpan, _: &mut StableHasher) { panic!(); } - fn def_path_hash(&self, _: RawDefId) -> RawDefPathHash { + fn def_path_hash(&self, _: RawDefId) -> Fingerprint { panic!(); } fn stable_hash_controls(&self) -> StableHashControls { diff --git a/compiler/rustc_middle/src/ich.rs b/compiler/rustc_middle/src/ich.rs index 1577e54a45bf7..20c4b3babe9e1 100644 --- a/compiler/rustc_middle/src/ich.rs +++ b/compiler/rustc_middle/src/ich.rs @@ -1,8 +1,9 @@ use std::hash::Hash; use rustc_crate_store::Untracked; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hash::{ - RawDefId, RawDefPathHash, RawSpan, StableHash, StableHashControls, StableHashCtxt, StableHasher, + RawDefId, RawSpan, StableHash, StableHashControls, StableHashCtxt, StableHasher, }; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_session::Session; @@ -159,14 +160,14 @@ impl<'a> StableHashCtxt for StableHashState<'a> { } #[inline] - fn def_path_hash(&self, raw_def_id: RawDefId) -> RawDefPathHash { + fn def_path_hash(&self, raw_def_id: RawDefId) -> Fingerprint { let def_id = DefId::from_raw_def_id(raw_def_id); if let Some(def_id) = def_id.as_local() { self.untracked.definitions.read().def_path_hash(def_id) } else { self.untracked.cstore.read().def_path_hash(def_id) } - .to_raw_def_path_hash() + .0 } /// Assert that the provided `StableHashCtxt` is configured with the default diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 43a0d18cde435..b2b5d2aa22bc1 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -4,7 +4,7 @@ use std::hash::{BuildHasherDefault, Hash, Hasher}; use rustc_data_structures::AtomicRef; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hash::{ - RawDefId, RawDefPathHash, StableHash, StableHashCtxt, StableHasher, StableOrd, ToStableHashKey, + RawDefId, StableHash, StableHashCtxt, StableHasher, StableOrd, ToStableHashKey, }; use rustc_data_structures::unhash::Unhasher; use rustc_hashes::Hash64; @@ -116,16 +116,6 @@ impl DefPathHash { pub fn new(stable_crate_id: StableCrateId, local_hash: Hash64) -> DefPathHash { DefPathHash(Fingerprint::new(stable_crate_id.0, local_hash)) } - - #[inline] - pub fn to_raw_def_path_hash(self) -> RawDefPathHash { - RawDefPathHash(self.0.to_le_bytes()) - } - - #[inline] - pub fn from_raw_def_path_hash(RawDefPathHash(a): RawDefPathHash) -> DefPathHash { - DefPathHash(Fingerprint::from_le_bytes(a)) - } } impl Default for DefPathHash { @@ -453,7 +443,7 @@ impl ToStableHashKey for DefId { #[inline] fn to_stable_hash_key(&self, hcx: &mut Hcx) -> DefPathHash { - DefPathHash::from_raw_def_path_hash(hcx.def_path_hash(self.to_raw_def_id())) + DefPathHash(hcx.def_path_hash(self.to_raw_def_id())) } } From 57bb4d118c2dd7a64b174e58e58a0eed4e723734 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Aug 2026 14:44:43 +0200 Subject: [PATCH 08/16] explicitly state that allocations cannot grow to the left --- library/core/src/ptr/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 2bdb12485dd68..f349259582447 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -159,10 +159,10 @@ //! //! Allocations typically have a fixed size that cannot change. However, allocations created by //! directly invoking page table operations of the operating system, e.g. via `mmap`, are allowed to -//! grow by adding more pages to them at the end. Unmapping parts of an allocation (i.e., shrinking -//! it or punching holes into it) is currently not supported. Allocations created via -//! "compiler-recognized" operations, such as `std::alloc` methods or `libc::malloc`, can never -//! change their size, even if they use `mmap` under the hood. +//! grow by adding more pages to them at the end. Adding more pages before the beginning, or +//! unmapping parts of an allocation (i.e., shrinking it or punching holes into it), is currently +//! not supported. Allocations created via "compiler-recognized" operations, such as `std::alloc` +//! methods or `libc::malloc`, can never change their size, even if they use `mmap` under the hood. //! //! [`null()`]: null //! From 4339216c765023bec646c3a7aba584d433c39f42 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Wed, 29 Jul 2026 21:03:01 +0000 Subject: [PATCH 09/16] panic_unwind: Use global_asm! for IMGREL relocations --- library/panic_unwind/src/seh.rs | 246 ++++++++++---------------------- 1 file changed, 78 insertions(+), 168 deletions(-) diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 455cb114bdedb..884a823aceef7 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -49,7 +49,7 @@ use alloc::boxed::Box; use alloc::panicking::PanicPayload; use core::any::Any; -use core::ffi::{c_int, c_uint, c_void}; +use core::ffi::c_void; use core::mem::ManuallyDrop; // NOTE(nbdd0121): The `canary` field is part of stable ABI. @@ -66,10 +66,8 @@ struct Exception { data: Option>, } -// First up, a whole bunch of type definitions. There's a few platform-specific -// oddities here, and a lot that's just blatantly copied from LLVM. The purpose -// of all this is to implement the `panic` function below through a call to -// `_CxxThrowException`. +// The purpose of all this is to implement the `panic` function below through a +// call to `_CxxThrowException`. // // This function takes two arguments. The first is a pointer to the data we're // passing in, which in this case is our trait object. Pretty easy to find! The @@ -80,8 +78,9 @@ struct Exception { // Currently the definition of this type [1] is a little hairy, and the main // oddity (and difference from the online article) is that on 32-bit the // pointers are pointers but on 64-bit the pointers are expressed as 32-bit -// offsets from the `__ImageBase` symbol. The `ptr_t` and `ptr!` macro in the -// modules below are used to express this. +// offsets from the image base. It's not currently possible to create a relative +// offset in const Rust code, so this is done using assembly with the `@IMGREL` +// relocation. // // The maze of type definitions also closely follows what LLVM emits for this // sort of operation. For example, if you compile this C++ code on MSVC and emit @@ -109,96 +108,6 @@ struct Exception { // // [1]: https://www.geoffchappell.com/studies/msvc/language/predefined/ -#[cfg(target_arch = "x86")] -mod imp { - #[repr(transparent)] - #[derive(Copy, Clone)] - pub(super) struct ptr_t(*mut u8); - - impl ptr_t { - pub(super) const fn null() -> Self { - Self(core::ptr::null_mut()) - } - - pub(super) const fn new(ptr: *mut u8) -> Self { - Self(ptr) - } - - pub(super) const fn raw(self) -> *mut u8 { - self.0 - } - } -} - -#[cfg(not(target_arch = "x86"))] -mod imp { - // On 64-bit systems, SEH represents pointers as 32-bit offsets from `__ImageBase`. - #[repr(transparent)] - #[derive(Copy, Clone)] - pub(super) struct ptr_t(u32); - - unsafe extern "C" { - static __ImageBase: u8; - } - - impl ptr_t { - pub(super) const fn null() -> Self { - Self(0) - } - - pub(super) fn new(ptr: *mut u8) -> Self { - // We need to expose the provenance of the pointer because it is not carried by - // the `u32`, while the FFI needs to have this provenance to excess our statics. - // - // NOTE(niluxv): we could use `MaybeUninit` instead to leak the provenance - // into the FFI. In theory then the other side would need to do some processing - // to get a pointer with correct provenance, but these system functions aren't - // going to be cross-lang LTOed anyway. However, using expose is shorter and - // requires less unsafe. - let addr: usize = ptr.expose_provenance(); - let image_base = (&raw const __ImageBase).addr(); - let offset: usize = addr - image_base; - Self(offset as u32) - } - - pub(super) const fn raw(self) -> u32 { - self.0 - } - } -} - -use imp::ptr_t; - -#[repr(C)] -struct _ThrowInfo { - pub attributes: c_uint, - pub pmfnUnwind: ptr_t, - pub pForwardCompat: ptr_t, - pub pCatchableTypeArray: ptr_t, -} - -#[repr(C)] -struct _CatchableTypeArray { - pub nCatchableTypes: c_int, - pub arrayOfCatchableTypes: [ptr_t; 1], -} - -#[repr(C)] -struct _CatchableType { - pub properties: c_uint, - pub pType: ptr_t, - pub thisDisplacement: _PMD, - pub sizeOrOffset: c_int, - pub copyFunction: ptr_t, -} - -#[repr(C)] -struct _PMD { - pub mdisp: c_int, - pub pdisp: c_int, - pub vdisp: c_int, -} - #[repr(C)] struct _TypeDescriptor { pub pVFTable: *const u8, @@ -206,6 +115,8 @@ struct _TypeDescriptor { pub name: [u8; 11], } +unsafe impl Sync for _TypeDescriptor {} + // Note that we intentionally ignore name mangling rules here: we don't want C++ // to be able to catch Rust panics by simply declaring a `struct rust_panic`. // @@ -213,24 +124,6 @@ struct _TypeDescriptor { // the one used in `compiler/rustc_codegen_llvm/src/intrinsic.rs`. const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; -static mut THROW_INFO: _ThrowInfo = _ThrowInfo { - attributes: 0, - pmfnUnwind: ptr_t::null(), - pForwardCompat: ptr_t::null(), - pCatchableTypeArray: ptr_t::null(), -}; - -static mut CATCHABLE_TYPE_ARRAY: _CatchableTypeArray = - _CatchableTypeArray { nCatchableTypes: 1, arrayOfCatchableTypes: [ptr_t::null()] }; - -static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { - properties: 0, - pType: ptr_t::null(), - thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 }, - sizeOrOffset: size_of::() as c_int, - copyFunction: ptr_t::null(), -}; - unsafe extern "C" { // The leading `\x01` byte here is actually a magical signal to LLVM to // *not* apply any other mangling like prefixing with a `_` character. @@ -240,7 +133,7 @@ unsafe extern "C" { // descriptors are referenced by the C++ EH structures defined above and // that we construct below. #[link_name = "\x01??_7type_info@@6B@"] - static TYPE_INFO_VTABLE: *const u8; + static TYPE_INFO_VTABLE: u8; } // This type descriptor is only used when throwing an exception. The catch part @@ -248,8 +141,8 @@ unsafe extern "C" { // // This is fine since the MSVC runtime uses string comparison on the type name // to match TypeDescriptors rather than pointer equality. -static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { - pVFTable: (&raw const TYPE_INFO_VTABLE) as *const _, +static TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { + pVFTable: &raw const TYPE_INFO_VTABLE, spare: core::ptr::null_mut(), name: TYPE_NAME, }; @@ -304,8 +197,6 @@ pub(crate) fn panic(data: &mut dyn PanicPayload) -> u32 { } unsafe fn throw_exception(data: Option>) -> ! { - use core::intrinsics::{AtomicOrdering, atomic_store}; - // _CxxThrowException executes entirely on this stack frame, so there's no // need to otherwise transfer `data` to the heap. We just pass a stack // pointer to this function. @@ -313,60 +204,79 @@ unsafe fn throw_exception(data: Option>) -> ! { // The ManuallyDrop is needed here since we don't want Exception to be // dropped when unwinding. Instead it will be dropped by exception_cleanup // which is invoked by the C++ runtime. - let mut exception = ManuallyDrop::new(Exception { canary: (&raw const TYPE_DESCRIPTOR), data }); - let throw_ptr = (&raw mut exception) as *mut _; + let mut exception = ManuallyDrop::new(Exception { canary: &raw const TYPE_DESCRIPTOR, data }); - // This... may seems surprising, and justifiably so. On 32-bit MSVC the - // pointers between these structure are just that, pointers. On 64-bit MSVC, - // however, the pointers between structures are rather expressed as 32-bit - // offsets from `__ImageBase`. - // - // Consequently, on 32-bit MSVC we can declare all these pointers in the - // `static`s above. On 64-bit MSVC, we would have to express subtraction of - // pointers in statics, which Rust does not currently allow, so we can't - // actually do that. - // - // The next best thing, then is to fill in these structures at runtime - // (panicking is already the "slow path" anyway). So here we reinterpret all - // of these pointer fields as 32-bit integers and then store the - // relevant value into it (atomically, as concurrent panics may be - // happening). Technically the runtime will probably do a nonatomic read of - // these fields, but in theory they never read the *wrong* value so it - // shouldn't be too bad... - // - // In any case, we basically need to do something like this until we can - // express more operations in statics (and we may never be able to). - unsafe { - #[allow(function_casts_as_integer)] - atomic_store::<_, { AtomicOrdering::SeqCst }, /* VOLATILE */ false>( - (&raw mut THROW_INFO.pmfnUnwind).cast(), - ptr_t::new(exception_cleanup as *mut u8).raw(), - ); - atomic_store::<_, { AtomicOrdering::SeqCst }, /* VOLATILE */ false>( - (&raw mut THROW_INFO.pCatchableTypeArray).cast(), - ptr_t::new((&raw mut CATCHABLE_TYPE_ARRAY).cast()).raw(), - ); - atomic_store::<_, { AtomicOrdering::SeqCst }, /* VOLATILE */ false>( - (&raw mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]).cast(), - ptr_t::new((&raw mut CATCHABLE_TYPE).cast()).raw(), - ); - atomic_store::<_, { AtomicOrdering::SeqCst }, /* VOLATILE */ false>( - (&raw mut CATCHABLE_TYPE.pType).cast(), - ptr_t::new((&raw mut TYPE_DESCRIPTOR).cast()).raw(), - ); - #[allow(function_casts_as_integer)] - atomic_store::<_, { AtomicOrdering::SeqCst }, /* VOLATILE */ false>( - (&raw mut CATCHABLE_TYPE.copyFunction).cast(), - ptr_t::new(exception_copy as *mut u8).raw(), - ); + unsafe extern "system-unwind" { + fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *const u8) -> !; } - unsafe extern "system-unwind" { - fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8) -> !; + #[cfg(target_arch = "x86")] + macro_rules! imgrel { + ($s:literal) => { + concat!(".long ", $s) + }; + } + #[cfg(not(target_arch = "x86"))] + macro_rules! imgrel { + ($s:literal) => { + concat!(".long ", $s, "@IMGREL") + }; } + let throw_info: *const u8; unsafe { - _CxxThrowException(throw_ptr, (&raw mut THROW_INFO) as *mut _); + core::arch::asm!( + cfg_select! { // let throw_info = &THROW_INFO; + target_arch = "x86" => { + "lea {}, [2f]" + } + target_arch = "x86_64" => { + "lea {}, [rip + 2f]" + } + target_arch = "arm" => { + concat!( + "movw {0}, :lower16:2f\n", + "movt {0}, :upper16:2f", + ) + } + any(target_arch = "aarch64", target_arch = "arm64ec") => { + concat!( + "adrp {0}, 2f\n", + "add {0}, {0}, :lo12:2f", + ) + } + }, + ".pushsection .rdata,\"dr\"", + ".p2align 2", + "2:", // static THROW_INFO = _ThrowInfo { + ".long 0", // attributes: 0, + imgrel!("{cleanup}"), // pmfnUnwind: exception_cleanup, + ".long 0", // pForwardCompat: ptr::null_mut(), + imgrel!("3f"), // pCatchableTypeArray: &CATCHABLE_TYPE_ARRAY, + // } + "3:", // static CATCHABLE_TYPE_ARRAY = _CatchableTypeArray { + ".long 1", // nCatchableTypes: 1, + imgrel!("4f"), // arrayOfCatchableTypes: [&CATCHABLE_TYPE], + // } + "4:", // static CATCHABLE_TYPE = _CatchableType { + ".long 0", // properties: 0, + imgrel!("{type_desc}"), // pType: &TYPE_DESCRIPTOR, + // thisDisplacement: _PMD { + ".long 0", // mdisp: 0, + ".long -1", // pdisp: -1, + ".long 0", // vdisp: 0, + // } + ".long {exception_size}", // sizeOrOffset: size_of::(), + imgrel!("{copy}"), // copyFunction: exception_copy, + ".popsection", // } + out(reg) throw_info, + cleanup = sym exception_cleanup, + type_desc = sym TYPE_DESCRIPTOR, + exception_size = const size_of::(), + copy = sym exception_copy, + options(readonly, nostack), + ); + _CxxThrowException((&raw mut exception).cast(), throw_info); } } From 1b2470e2cc3186cc3934877dbd0ae76ae41a416d Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:06:11 +0100 Subject: [PATCH 10/16] bring back warns for repeated reprs, update tests had to update several tests which used repeated aligns and packeds. they now produce both a warning and an error where appropriate (e.g. when using conflicting packeds) which i think is correct. --- compiler/rustc_passes/src/check_attr.rs | 7 +-- tests/ui/attributes/issue-100631.rs | 1 + tests/ui/attributes/issue-100631.stderr | 16 ++++- tests/ui/lint/unused/unused-attr-duplicate.rs | 3 +- .../lint/unused/unused-attr-duplicate.stderr | 62 +++++++++++++------ tests/ui/repr/conflicting-repr-hints.rs | 6 +- tests/ui/repr/conflicting-repr-hints.stderr | 29 ++++++++- tests/ui/structs-enums/align-enum.rs | 2 +- tests/ui/structs-enums/align-enum.stderr | 15 +++++ tests/ui/structs-enums/align-struct.rs | 2 +- tests/ui/structs-enums/align-struct.stderr | 15 +++++ 11 files changed, 125 insertions(+), 33 deletions(-) create mode 100644 tests/ui/structs-enums/align-enum.stderr create mode 100644 tests/ui/structs-enums/align-struct.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5aeb1b3ec2a02..ea045ac6465f3 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1221,7 +1221,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match repr { ReprAttr::ReprRust => { if is_explicit_rust { - repeated_repr = true + repeated_repr = true; } is_explicit_rust = true; } @@ -1250,9 +1250,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { is_simd = true; } ReprAttr::ReprTransparent => { - if is_transparent { - repeated_repr = true; - } + // No need to check for repeated transparent because that is already checked + // when checking for any other attribute together with transparent. is_transparent = true; } ReprAttr::ReprInt(_) => { diff --git a/tests/ui/attributes/issue-100631.rs b/tests/ui/attributes/issue-100631.rs index 0fefcf83fd516..0f0eb235aae78 100644 --- a/tests/ui/attributes/issue-100631.rs +++ b/tests/ui/attributes/issue-100631.rs @@ -2,6 +2,7 @@ // can reasonably deal with multiple attributes. // `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`. #[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084] +//~^ WARN attribute is specified more than once #[repr(C)] enum Foo {} diff --git a/tests/ui/attributes/issue-100631.stderr b/tests/ui/attributes/issue-100631.stderr index b2bd0a9632513..8f9cc9defcde0 100644 --- a/tests/ui/attributes/issue-100631.stderr +++ b/tests/ui/attributes/issue-100631.stderr @@ -1,12 +1,24 @@ -error[E0084]: unsupported representation for zero-variant enum +warning: attribute is specified more than once --> $DIR/issue-100631.rs:4:8 | LL | #[repr(C)] | ^ +LL | LL | #[repr(C)] + | ^ + | + = note: will become a hard error soon. todo: wording + = note: `#[warn(repeated_reprs)]` on by default + +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/issue-100631.rs:4:8 + | +LL | #[repr(C)] + | ^ +... LL | enum Foo {} | -------- zero-variant enum -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0084`. diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs index 54c040f4bcac4..6a1dfd702cf06 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.rs +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -64,8 +64,7 @@ fn t1() {} #[must_use = "some message"] //~^ ERROR unused attribute //~| WARN this was previously accepted -// No warnings for #[repr], would require more logic. -#[repr(C)] +#[repr(C)] //~ WARN attribute is specified more than once #[repr(C)] #[non_exhaustive] #[non_exhaustive] //~ ERROR unused attribute diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 3e4cb99a09e34..10a674cc03325 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -16,6 +16,17 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ +warning: attribute is specified more than once + --> $DIR/unused-attr-duplicate.rs:67:8 + | +LL | #[repr(C)] + | ^ +LL | #[repr(C)] + | ^ + | + = note: will become a hard error soon. todo: wording + = note: `#[warn(repeated_reprs)]` on by default + error: unused attribute --> $DIR/unused-attr-duplicate.rs:14:1 | @@ -193,111 +204,124 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:71:1 + --> $DIR/unused-attr-duplicate.rs:70:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:70:1 + --> $DIR/unused-attr-duplicate.rs:69:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:77:1 + --> $DIR/unused-attr-duplicate.rs:76:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:76:1 + --> $DIR/unused-attr-duplicate.rs:75:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:81:1 + --> $DIR/unused-attr-duplicate.rs:80:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:80:1 + --> $DIR/unused-attr-duplicate.rs:79:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:84:1 + --> $DIR/unused-attr-duplicate.rs:83:1 | LL | #[cold] | ^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:83:1 + --> $DIR/unused-attr-duplicate.rs:82:1 | LL | #[cold] | ^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:86:1 + --> $DIR/unused-attr-duplicate.rs:85:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:85:1 + --> $DIR/unused-attr-duplicate.rs:84:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:100:1 + --> $DIR/unused-attr-duplicate.rs:93:5 + | +LL | #[link_name = "rust_dbg_extern_identity_u32"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:92:5 + | +LL | #[link_name = "this_does_not_exist"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:99:1 | LL | #[export_name = "exported_symbol_name2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:99:1 + --> $DIR/unused-attr-duplicate.rs:98:1 | LL | #[export_name = "exported_symbol_name"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:105:1 + --> $DIR/unused-attr-duplicate.rs:104:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:104:1 + --> $DIR/unused-attr-duplicate.rs:103:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:109:1 + --> $DIR/unused-attr-duplicate.rs:108:1 | LL | #[used] | ^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:108:1 + --> $DIR/unused-attr-duplicate.rs:107:1 | LL | #[used] | ^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:113:1 + --> $DIR/unused-attr-duplicate.rs:112:1 | LL | #[link_section = "__DATA,__mod_init_func"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:112:1 + --> $DIR/unused-attr-duplicate.rs:111:1 | LL | #[link_section = "__TEXT,__text"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -316,5 +340,5 @@ LL | #[link_name = "this_does_not_exist"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: aborting due to 25 previous errors +error: aborting due to 25 previous errors; 1 warning emitted diff --git a/tests/ui/repr/conflicting-repr-hints.rs b/tests/ui/repr/conflicting-repr-hints.rs index ed82b6a742c8d..0ddcabef67972 100644 --- a/tests/ui/repr/conflicting-repr-hints.rs +++ b/tests/ui/repr/conflicting-repr-hints.rs @@ -36,14 +36,14 @@ struct G(i32); //~ ERROR type has conflicting packed and align representation hi #[repr(packed)] struct H(i32); //~ ERROR type has conflicting packed and align representation hints -#[repr(packed, packed(2))] +#[repr(packed, packed(2))] //~ WARN attribute is specified more than once struct I(i32); //~ ERROR type has conflicting packed representation hints -#[repr(packed(2))] +#[repr(packed(2))] //~ WARN attribute is specified more than once #[repr(packed)] struct J(i32); //~ ERROR type has conflicting packed representation hints -#[repr(packed, packed(1))] +#[repr(packed, packed(1))] //~ WARN attribute is specified more than once struct K(i32); #[repr(packed, align(8))] diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr index 4da3d454e037d..77ff01a22caa5 100644 --- a/tests/ui/repr/conflicting-repr-hints.stderr +++ b/tests/ui/repr/conflicting-repr-hints.stderr @@ -17,6 +17,33 @@ LL | #[repr(u32, u64)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 +warning: attribute is specified more than once + --> $DIR/conflicting-repr-hints.rs:39:8 + | +LL | #[repr(packed, packed(2))] + | ^^^^^^ ^^^^^^^^^ + | + = note: will become a hard error soon. todo: wording + = note: `#[warn(repeated_reprs)]` on by default + +warning: attribute is specified more than once + --> $DIR/conflicting-repr-hints.rs:42:8 + | +LL | #[repr(packed(2))] + | ^^^^^^^^^ +LL | #[repr(packed)] + | ^^^^^^ + | + = note: will become a hard error soon. todo: wording + +warning: attribute is specified more than once + --> $DIR/conflicting-repr-hints.rs:46:8 + | +LL | #[repr(packed, packed(1))] + | ^^^^^^ ^^^^^^^^^ + | + = note: will become a hard error soon. todo: wording + error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:29:1 | @@ -77,7 +104,7 @@ error[E0587]: type has conflicting packed and align representation hints LL | pub union U { | ^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 12 previous errors; 3 warnings emitted Some errors have detailed explanations: E0566, E0587, E0634. For more information about an error, try `rustc --explain E0566`. diff --git a/tests/ui/structs-enums/align-enum.rs b/tests/ui/structs-enums/align-enum.rs index ff80a19211cda..c9652ac84db47 100644 --- a/tests/ui/structs-enums/align-enum.rs +++ b/tests/ui/structs-enums/align-enum.rs @@ -11,7 +11,7 @@ enum Align16 { } // Raise alignment by maximum -#[repr(align(1), align(16))] +#[repr(align(1), align(16))] //~ WARN attribute is specified more than once #[repr(align(32))] #[repr(align(4))] enum Align32 { diff --git a/tests/ui/structs-enums/align-enum.stderr b/tests/ui/structs-enums/align-enum.stderr new file mode 100644 index 0000000000000..25fec15cf2a12 --- /dev/null +++ b/tests/ui/structs-enums/align-enum.stderr @@ -0,0 +1,15 @@ +warning: attribute is specified more than once + --> $DIR/align-enum.rs:14:8 + | +LL | #[repr(align(1), align(16))] + | ^^^^^^^^ ^^^^^^^^^ +LL | #[repr(align(32))] + | ^^^^^^^^^ +LL | #[repr(align(4))] + | ^^^^^^^^ + | + = note: will become a hard error soon. todo: wording + = note: `#[warn(repeated_reprs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/structs-enums/align-struct.rs b/tests/ui/structs-enums/align-struct.rs index 3d8dad6e324e3..1b6d4dfa49755 100644 --- a/tests/ui/structs-enums/align-struct.rs +++ b/tests/ui/structs-enums/align-struct.rs @@ -13,7 +13,7 @@ struct Align16(i32); struct Align1(i32); // Multiple attributes take the max -#[repr(align(4))] +#[repr(align(4))] //~ WARN attribute is specified more than once #[repr(align(16))] #[repr(align(8))] struct AlignMany(i32); diff --git a/tests/ui/structs-enums/align-struct.stderr b/tests/ui/structs-enums/align-struct.stderr new file mode 100644 index 0000000000000..6aaafc8c7753d --- /dev/null +++ b/tests/ui/structs-enums/align-struct.stderr @@ -0,0 +1,15 @@ +warning: attribute is specified more than once + --> $DIR/align-struct.rs:16:8 + | +LL | #[repr(align(4))] + | ^^^^^^^^ +LL | #[repr(align(16))] + | ^^^^^^^^^ +LL | #[repr(align(8))] + | ^^^^^^^^ + | + = note: will become a hard error soon. todo: wording + = note: `#[warn(repeated_reprs)]` on by default + +warning: 1 warning emitted + From 6423eed93f6662dee0d087dd3f237de0aaca69b0 Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:06:25 +0100 Subject: [PATCH 11/16] finish rewording lint messages --- compiler/rustc_lint_defs/src/builtin.rs | 15 +++++++++++---- compiler/rustc_passes/src/diagnostics.rs | 4 ++-- tests/ui/attributes/issue-100631.rs | 2 +- tests/ui/attributes/issue-100631.stderr | 4 ++-- tests/ui/lint/unused/unused-attr-duplicate.rs | 2 +- tests/ui/lint/unused/unused-attr-duplicate.stderr | 4 ++-- tests/ui/repr/conflicting-repr-hints.rs | 4 ++-- tests/ui/repr/conflicting-repr-hints.stderr | 12 ++++++------ tests/ui/structs-enums/align-enum.rs | 2 +- tests/ui/structs-enums/align-enum.stderr | 4 ++-- tests/ui/structs-enums/align-struct.rs | 2 +- tests/ui/structs-enums/align-struct.stderr | 4 ++-- 12 files changed, 33 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index af517fbd8f4d0..811536a5f221e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -278,18 +278,25 @@ declare_lint! { } declare_lint! { - /// Todo: explain this. + /// The `repeated_reprs` lint detects when the same representation is + /// specified more than once in a `#[repr(..)]` attribute. /// /// ### Example /// - /// TODO + /// ```rust + /// #[repr(C)] + /// #[repr(C)] + /// enum Foo { A } + /// ``` /// /// ### Explanation /// - /// TODO + /// While some representations may be specified more than once, the compiler + /// will reject repeated uses of some others. For consistency, prefer to + /// only specify the representation once. pub REPEATED_REPRS, Warn, - "repeated `#[repr(..)]` attributes were inconsistently rejected before", + "detects repeated representations in `#[repr(..)]` attributes", } declare_lint! { diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index deae750ca2688..2f4900a6b47a7 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -608,8 +608,8 @@ pub(crate) struct TransparentIncompatible { } #[derive(Diagnostic)] -#[diag("attribute is specified more than once")] -#[note("will become a hard error soon. todo: wording")] +#[diag("representation attribute is specified more than once")] +#[note("for consistency, only specify the representation once")] pub(crate) struct RepeatedRepr; #[derive(Diagnostic)] diff --git a/tests/ui/attributes/issue-100631.rs b/tests/ui/attributes/issue-100631.rs index 0f0eb235aae78..d496231c73026 100644 --- a/tests/ui/attributes/issue-100631.rs +++ b/tests/ui/attributes/issue-100631.rs @@ -2,7 +2,7 @@ // can reasonably deal with multiple attributes. // `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`. #[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084] -//~^ WARN attribute is specified more than once +//~^ WARN representation attribute is specified more than once #[repr(C)] enum Foo {} diff --git a/tests/ui/attributes/issue-100631.stderr b/tests/ui/attributes/issue-100631.stderr index 8f9cc9defcde0..66e08738eb02c 100644 --- a/tests/ui/attributes/issue-100631.stderr +++ b/tests/ui/attributes/issue-100631.stderr @@ -1,4 +1,4 @@ -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/issue-100631.rs:4:8 | LL | #[repr(C)] @@ -7,7 +7,7 @@ LL | LL | #[repr(C)] | ^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once = note: `#[warn(repeated_reprs)]` on by default error[E0084]: unsupported representation for zero-variant enum diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs index 6a1dfd702cf06..348c9590e8b27 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.rs +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -64,7 +64,7 @@ fn t1() {} #[must_use = "some message"] //~^ ERROR unused attribute //~| WARN this was previously accepted -#[repr(C)] //~ WARN attribute is specified more than once +#[repr(C)] //~ WARN representation attribute is specified more than once #[repr(C)] #[non_exhaustive] #[non_exhaustive] //~ ERROR unused attribute diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 10a674cc03325..93f7a4791188f 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -16,7 +16,7 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/unused-attr-duplicate.rs:67:8 | LL | #[repr(C)] @@ -24,7 +24,7 @@ LL | #[repr(C)] LL | #[repr(C)] | ^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once = note: `#[warn(repeated_reprs)]` on by default error: unused attribute diff --git a/tests/ui/repr/conflicting-repr-hints.rs b/tests/ui/repr/conflicting-repr-hints.rs index 0ddcabef67972..032f2b2e6c608 100644 --- a/tests/ui/repr/conflicting-repr-hints.rs +++ b/tests/ui/repr/conflicting-repr-hints.rs @@ -36,10 +36,10 @@ struct G(i32); //~ ERROR type has conflicting packed and align representation hi #[repr(packed)] struct H(i32); //~ ERROR type has conflicting packed and align representation hints -#[repr(packed, packed(2))] //~ WARN attribute is specified more than once +#[repr(packed, packed(2))] //~ WARN representation attribute is specified more than once struct I(i32); //~ ERROR type has conflicting packed representation hints -#[repr(packed(2))] //~ WARN attribute is specified more than once +#[repr(packed(2))] //~ WARN representation attribute is specified more than once #[repr(packed)] struct J(i32); //~ ERROR type has conflicting packed representation hints diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr index 77ff01a22caa5..a99546b754785 100644 --- a/tests/ui/repr/conflicting-repr-hints.stderr +++ b/tests/ui/repr/conflicting-repr-hints.stderr @@ -17,16 +17,16 @@ LL | #[repr(u32, u64)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/conflicting-repr-hints.rs:39:8 | LL | #[repr(packed, packed(2))] | ^^^^^^ ^^^^^^^^^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once = note: `#[warn(repeated_reprs)]` on by default -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/conflicting-repr-hints.rs:42:8 | LL | #[repr(packed(2))] @@ -34,15 +34,15 @@ LL | #[repr(packed(2))] LL | #[repr(packed)] | ^^^^^^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/conflicting-repr-hints.rs:46:8 | LL | #[repr(packed, packed(1))] | ^^^^^^ ^^^^^^^^^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:29:1 diff --git a/tests/ui/structs-enums/align-enum.rs b/tests/ui/structs-enums/align-enum.rs index c9652ac84db47..a635af7352afe 100644 --- a/tests/ui/structs-enums/align-enum.rs +++ b/tests/ui/structs-enums/align-enum.rs @@ -11,7 +11,7 @@ enum Align16 { } // Raise alignment by maximum -#[repr(align(1), align(16))] //~ WARN attribute is specified more than once +#[repr(align(1), align(16))] //~ WARN representation attribute is specified more than once #[repr(align(32))] #[repr(align(4))] enum Align32 { diff --git a/tests/ui/structs-enums/align-enum.stderr b/tests/ui/structs-enums/align-enum.stderr index 25fec15cf2a12..9b8c9842f81df 100644 --- a/tests/ui/structs-enums/align-enum.stderr +++ b/tests/ui/structs-enums/align-enum.stderr @@ -1,4 +1,4 @@ -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/align-enum.rs:14:8 | LL | #[repr(align(1), align(16))] @@ -8,7 +8,7 @@ LL | #[repr(align(32))] LL | #[repr(align(4))] | ^^^^^^^^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once = note: `#[warn(repeated_reprs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/structs-enums/align-struct.rs b/tests/ui/structs-enums/align-struct.rs index 1b6d4dfa49755..2d1ebf6731a62 100644 --- a/tests/ui/structs-enums/align-struct.rs +++ b/tests/ui/structs-enums/align-struct.rs @@ -13,7 +13,7 @@ struct Align16(i32); struct Align1(i32); // Multiple attributes take the max -#[repr(align(4))] //~ WARN attribute is specified more than once +#[repr(align(4))] //~ WARN representation attribute is specified more than once #[repr(align(16))] #[repr(align(8))] struct AlignMany(i32); diff --git a/tests/ui/structs-enums/align-struct.stderr b/tests/ui/structs-enums/align-struct.stderr index 6aaafc8c7753d..f54e9cd14cd8b 100644 --- a/tests/ui/structs-enums/align-struct.stderr +++ b/tests/ui/structs-enums/align-struct.stderr @@ -1,4 +1,4 @@ -warning: attribute is specified more than once +warning: representation attribute is specified more than once --> $DIR/align-struct.rs:16:8 | LL | #[repr(align(4))] @@ -8,7 +8,7 @@ LL | #[repr(align(16))] LL | #[repr(align(8))] | ^^^^^^^^ | - = note: will become a hard error soon. todo: wording + = note: for consistency, only specify the representation once = note: `#[warn(repeated_reprs)]` on by default warning: 1 warning emitted From deb81605189b7df985187428eb2ef9f934e2804d Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:06:29 +0100 Subject: [PATCH 12/16] add another test --- compiler/rustc_lint_defs/src/builtin.rs | 2 + tests/ui/repr/repr-repeated-attrs.rs | 68 ++++++++ tests/ui/repr/repr-repeated-attrs.stderr | 200 +++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 tests/ui/repr/repr-repeated-attrs.rs create mode 100644 tests/ui/repr/repr-repeated-attrs.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 811536a5f221e..11cdbea3c426a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -289,6 +289,8 @@ declare_lint! { /// enum Foo { A } /// ``` /// + /// {{produces}} + /// /// ### Explanation /// /// While some representations may be specified more than once, the compiler diff --git a/tests/ui/repr/repr-repeated-attrs.rs b/tests/ui/repr/repr-repeated-attrs.rs new file mode 100644 index 0000000000000..a6dd3fb6e8b15 --- /dev/null +++ b/tests/ui/repr/repr-repeated-attrs.rs @@ -0,0 +1,68 @@ +// Tests to ensure we warn on repeated `#[repr(..)]` attributes. + +#[repr(transparent, transparent)] +//~^ ERROR transparent struct cannot have other repr hints +#[repr(transparent)] +struct SeveralTransparentReprs(*mut u8); + +#[repr(transparent)] +//~^ ERROR transparent struct cannot have other repr hints +#[repr(transparent)] +struct MultilineOnly(*mut u8); + +#[repr(Rust, Rust)] +//~^ WARN representation attribute is specified more than once +struct SeveralRustReprs(u8); + +#[repr(C, C)] +//~^ WARN representation attribute is specified more than once +#[repr(C, C, C)] +struct SeveralC(u8); + +#[repr(u8, u8)] +//~^ ERROR conflicting representation hints +//~| WARN this was previously accepted +enum SeveralPrimitiveRerprs { + Variant, +} + +#[repr(C, C, u8)] //~ WARN representation attribute is specified more than once +//~^ ERROR conflicting representation hints +//~| WARN this was previously accepted +#[repr(C, u8, u8)] +enum SeveralCAndPrims { + Variant(u8), +} + +#[repr(Rust, u8, u8)] +//~^ ERROR conflicting representation hints +//~^^ ERROR conflicting representation hints +//~| WARN this was previously accepted +enum RustAndPrimDisallowed { + Variant(u8), +} + +#[repr(u8, u8)] //~ ERROR conflicting representation hints +//~^ WARN this was previously accepted +#[repr(u16)] +enum ConflictingPrimReprs { + Variant, +} + +#[repr(C, u8)] +//~^ ERROR conflicting representation hints +//~| WARN this was previously accepted +enum CWithIntsCausesFCW1 { + A, + B, +} + +#[repr(C, C, u8, u8, u8)] //~ WARN representation attribute is specified more than once +//~^ ERROR conflicting representation hints +//~| WARN this was previously accepted +enum CWithIntsCausesFCW2 { + A, + B, +} + +fn main() {} diff --git a/tests/ui/repr/repr-repeated-attrs.stderr b/tests/ui/repr/repr-repeated-attrs.stderr new file mode 100644 index 0000000000000..72c312a13ea11 --- /dev/null +++ b/tests/ui/repr/repr-repeated-attrs.stderr @@ -0,0 +1,200 @@ +error[E0692]: transparent struct cannot have other repr hints + --> $DIR/repr-repeated-attrs.rs:3:8 + | +LL | #[repr(transparent, transparent)] + | ^^^^^^^^^^^ ^^^^^^^^^^^ +LL | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ + +error[E0692]: transparent struct cannot have other repr hints + --> $DIR/repr-repeated-attrs.rs:8:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +LL | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ + +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:13:8 + | +LL | #[repr(Rust, Rust)] + | ^^^^ ^^^^ + | + = note: for consistency, only specify the representation once + = note: `#[warn(repeated_reprs)]` on by default + +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:17:8 + | +LL | #[repr(C, C)] + | ^ ^ +LL | +LL | #[repr(C, C, C)] + | ^ ^ ^ + | + = note: for consistency, only specify the representation once + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:22:8 + | +LL | #[repr(u8, u8)] + | ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:29:8 + | +LL | #[repr(C, C, u8)] + | ^ ^ ^^ +... +LL | #[repr(C, u8, u8)] + | ^ ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:29:8 + | +LL | #[repr(C, C, u8)] + | ^ ^ ^^ +... +LL | #[repr(C, u8, u8)] + | ^ ^^ ^^ + | + = note: for consistency, only specify the representation once + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:37:8 + | +LL | #[repr(Rust, u8, u8)] + | ^^^^ ^^ ^^ + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:37:8 + | +LL | #[repr(Rust, u8, u8)] + | ^^^^ ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:44:8 + | +LL | #[repr(u8, u8)] + | ^^ ^^ +LL | +LL | #[repr(u16)] + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:51:8 + | +LL | #[repr(C, u8)] + | ^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:59:8 + | +LL | #[repr(C, C, u8, u8, u8)] + | ^ ^ ^^ ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:59:8 + | +LL | #[repr(C, C, u8, u8, u8)] + | ^ ^ ^^ ^^ ^^ + | + = note: for consistency, only specify the representation once + +error: aborting due to 9 previous errors; 4 warnings emitted + +Some errors have detailed explanations: E0566, E0692. +For more information about an error, try `rustc --explain E0566`. +Future incompatibility report: Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:22:8 + | +LL | #[repr(u8, u8)] + | ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:29:8 + | +LL | #[repr(C, C, u8)] + | ^ ^ ^^ +... +LL | #[repr(C, u8, u8)] + | ^ ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:37:8 + | +LL | #[repr(Rust, u8, u8)] + | ^^^^ ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:44:8 + | +LL | #[repr(u8, u8)] + | ^^ ^^ +LL | +LL | #[repr(u16)] + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:51:8 + | +LL | #[repr(C, u8)] + | ^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + +Future breakage diagnostic: +error[E0566]: conflicting representation hints + --> $DIR/repr-repeated-attrs.rs:59:8 + | +LL | #[repr(C, C, u8, u8, u8)] + | ^ ^ ^^ ^^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + From 4f5002db4e071f169e670097913a63f16f305492 Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:06:37 +0100 Subject: [PATCH 13/16] also warn on repeated int reprs --- compiler/rustc_passes/src/check_attr.rs | 13 ++++++- tests/ui/repr/repr-repeated-attrs.rs | 9 +++-- tests/ui/repr/repr-repeated-attrs.stderr | 47 +++++++++++++++++++----- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ea045ac6465f3..b196ae1e5a82e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1216,6 +1216,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let mut is_align = false; let mut is_packed = false; let mut repeated_repr = false; + let mut maybe_last_int_type = None; for (repr, _repr_span) in reprs { match repr { @@ -1254,7 +1255,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // when checking for any other attribute together with transparent. is_transparent = true; } - ReprAttr::ReprInt(_) => { + ReprAttr::ReprInt(int_type) => { + if let Some(last_int_type) = maybe_last_int_type + && last_int_type == int_type + { + // We'll "miss" detecting repeated int reprs if the user specifies + // #[repr(u8, u64, u8)] for example. But that's okay because we've got + // conflicting reprs anyway so it's not worth the effort to do more precise + // tracking. + repeated_repr = true; + } + maybe_last_int_type = Some(int_type); int_reprs += 1; } }; diff --git a/tests/ui/repr/repr-repeated-attrs.rs b/tests/ui/repr/repr-repeated-attrs.rs index a6dd3fb6e8b15..61e3ba05625d8 100644 --- a/tests/ui/repr/repr-repeated-attrs.rs +++ b/tests/ui/repr/repr-repeated-attrs.rs @@ -19,7 +19,7 @@ struct SeveralRustReprs(u8); #[repr(C, C, C)] struct SeveralC(u8); -#[repr(u8, u8)] +#[repr(u8, u8)] //~ WARN representation attribute is specified more than once //~^ ERROR conflicting representation hints //~| WARN this was previously accepted enum SeveralPrimitiveRerprs { @@ -34,7 +34,7 @@ enum SeveralCAndPrims { Variant(u8), } -#[repr(Rust, u8, u8)] +#[repr(Rust, u8, u8)] //~ WARN representation attribute is specified more than once //~^ ERROR conflicting representation hints //~^^ ERROR conflicting representation hints //~| WARN this was previously accepted @@ -42,8 +42,9 @@ enum RustAndPrimDisallowed { Variant(u8), } -#[repr(u8, u8)] //~ ERROR conflicting representation hints -//~^ WARN this was previously accepted +#[repr(u8, u8)] //~ WARN representation attribute is specified more than once +//~^ ERROR conflicting representation hints +//~| WARN this was previously accepted #[repr(u16)] enum ConflictingPrimReprs { Variant, diff --git a/tests/ui/repr/repr-repeated-attrs.stderr b/tests/ui/repr/repr-repeated-attrs.stderr index 72c312a13ea11..57af8ec804d76 100644 --- a/tests/ui/repr/repr-repeated-attrs.stderr +++ b/tests/ui/repr/repr-repeated-attrs.stderr @@ -46,6 +46,14 @@ LL | #[repr(u8, u8)] = note: for more information, see issue #68585 = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:22:8 + | +LL | #[repr(u8, u8)] + | ^^ ^^ + | + = note: for consistency, only specify the representation once + error[E0566]: conflicting representation hints --> $DIR/repr-repeated-attrs.rs:29:8 | @@ -84,20 +92,39 @@ LL | #[repr(Rust, u8, u8)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:37:8 + | +LL | #[repr(Rust, u8, u8)] + | ^^^^ ^^ ^^ + | + = note: for consistency, only specify the representation once + error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:44:8 + --> $DIR/repr-repeated-attrs.rs:45:8 | LL | #[repr(u8, u8)] | ^^ ^^ -LL | +... LL | #[repr(u16)] | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 +warning: representation attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:45:8 + | +LL | #[repr(u8, u8)] + | ^^ ^^ +... +LL | #[repr(u16)] + | ^^^ + | + = note: for consistency, only specify the representation once + error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:51:8 + --> $DIR/repr-repeated-attrs.rs:53:8 | LL | #[repr(C, u8)] | ^ ^^ @@ -106,7 +133,7 @@ LL | #[repr(C, u8)] = note: for more information, see issue #68585 error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:59:8 + --> $DIR/repr-repeated-attrs.rs:61:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ @@ -115,14 +142,14 @@ LL | #[repr(C, C, u8, u8, u8)] = note: for more information, see issue #68585 warning: representation attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:59:8 + --> $DIR/repr-repeated-attrs.rs:61:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ | = note: for consistency, only specify the representation once -error: aborting due to 9 previous errors; 4 warnings emitted +error: aborting due to 9 previous errors; 7 warnings emitted Some errors have detailed explanations: E0566, E0692. For more information about an error, try `rustc --explain E0566`. @@ -164,11 +191,11 @@ LL | #[repr(Rust, u8, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:44:8 + --> $DIR/repr-repeated-attrs.rs:45:8 | LL | #[repr(u8, u8)] | ^^ ^^ -LL | +... LL | #[repr(u16)] | ^^^ | @@ -178,7 +205,7 @@ LL | #[repr(u16)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:51:8 + --> $DIR/repr-repeated-attrs.rs:53:8 | LL | #[repr(C, u8)] | ^ ^^ @@ -189,7 +216,7 @@ LL | #[repr(C, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:59:8 + --> $DIR/repr-repeated-attrs.rs:61:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ From 819099b56c2c69e5ed886b4b4f1c572beefa749d Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:06:47 +0100 Subject: [PATCH 14/16] use sort/chunk_by to find repeated reprs --- compiler/rustc_attr_ir/src/data_structures.rs | 16 +++- compiler/rustc_passes/src/check_attr.rs | 81 +++++++---------- compiler/rustc_passes/src/diagnostics.rs | 2 +- tests/ui/attributes/issue-100631.rs | 2 +- tests/ui/attributes/issue-100631.stderr | 2 +- tests/ui/lint/unused/unused-attr-duplicate.rs | 2 +- .../lint/unused/unused-attr-duplicate.stderr | 19 +--- tests/ui/repr/conflicting-repr-hints.rs | 4 +- tests/ui/repr/conflicting-repr-hints.stderr | 24 +---- tests/ui/repr/repr-repeated-attrs.rs | 18 ++-- tests/ui/repr/repr-repeated-attrs.stderr | 87 +++++++++++-------- tests/ui/structs-enums/align-enum.rs | 2 +- tests/ui/structs-enums/align-enum.stderr | 15 ---- tests/ui/structs-enums/align-struct.rs | 2 +- tests/ui/structs-enums/align-struct.stderr | 15 ---- 15 files changed, 123 insertions(+), 168 deletions(-) delete mode 100644 tests/ui/structs-enums/align-enum.stderr delete mode 100644 tests/ui/structs-enums/align-struct.stderr diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 195712559782d..28e90ea4f52b4 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -172,7 +172,19 @@ impl OptimizeAttr { } } -#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, StableHash, PrintAttribute)] +#[derive( + PartialEq, + Eq, + Debug, + PartialOrd, + Ord, + Encodable, + Decodable, + Copy, + Clone, + StableHash, + PrintAttribute +)] pub enum ReprAttr { ReprInt(IntType), ReprRust, @@ -188,7 +200,7 @@ pub enum TransparencyError { MultipleTransparencyAttrs(Span, Span), } -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, PartialOrd, Ord)] #[derive(Encodable, Decodable, StableHash, PrintAttribute)] pub enum IntType { SignedInt(ast::IntTy), diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b196ae1e5a82e..e4ee552d5bd0e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1213,64 +1213,58 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let mut is_c = false; let mut is_simd = false; let mut is_transparent = false; - let mut is_align = false; - let mut is_packed = false; - let mut repeated_repr = false; - let mut maybe_last_int_type = None; for (repr, _repr_span) in reprs { match repr { ReprAttr::ReprRust => { - if is_explicit_rust { - repeated_repr = true; - } is_explicit_rust = true; } ReprAttr::ReprC => { - if is_c { - repeated_repr = true; - } is_c = true; } - ReprAttr::ReprAlign(..) => { - if is_align { - repeated_repr = true; - } - is_align = true; - } - ReprAttr::ReprPacked(..) => { - if is_packed { - repeated_repr = true; - } - is_packed = true; - } + ReprAttr::ReprAlign(..) => (), + ReprAttr::ReprPacked(..) => (), ReprAttr::ReprSimd => { - if is_simd { - repeated_repr = true; - } is_simd = true; } ReprAttr::ReprTransparent => { - // No need to check for repeated transparent because that is already checked - // when checking for any other attribute together with transparent. is_transparent = true; } - ReprAttr::ReprInt(int_type) => { - if let Some(last_int_type) = maybe_last_int_type - && last_int_type == int_type - { - // We'll "miss" detecting repeated int reprs if the user specifies - // #[repr(u8, u64, u8)] for example. But that's okay because we've got - // conflicting reprs anyway so it's not worth the effort to do more precise - // tracking. - repeated_repr = true; - } - maybe_last_int_type = Some(int_type); + ReprAttr::ReprInt(..) => { int_reprs += 1; } }; } + if !reprs.is_empty() { + let sorted_reprs = { + let mut to_sort = reprs.to_owned(); + to_sort.sort_unstable(); + to_sort + }; + + // To collect all duplicates, get subslices where all of the elements of the subslice + // are equal, then filter out all those whose length is not 1. We could return warnings + // for each of them, but that's annoyingly excessive. So we instead collect all spans in + // one big Vec. + let spans: Vec = sorted_reprs + .chunk_by(|(a, _), (b, _)| a == b) + .map(ToOwned::to_owned) + .filter(|slice| slice.len() != 1) + .flatten() + .map(|(_, span)| span) + .collect(); + + if !spans.is_empty() { + self.tcx.emit_node_span_lint( + REPEATED_REPRS, + hir_id, + spans, + diagnostics::RepeatedRepr, + ); + } + } + // Just point at all repr hints if there are any incompatibilities. // This is not ideal, but tracking precisely which ones are at fault is a huge hassle. let hint_spans = reprs.iter().map(|(_, span)| *span); @@ -1306,17 +1300,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( CONFLICTING_REPR_HINTS, hir_id, - hint_spans.clone().collect::>(), - diagnostics::ReprConflictingLint, - ); - } - - if repeated_repr { - self.tcx.emit_node_span_lint( - REPEATED_REPRS, - hir_id, hint_spans.collect::>(), - diagnostics::RepeatedRepr, + diagnostics::ReprConflictingLint, ); } } diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 2f4900a6b47a7..c343d9c7078e7 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -608,7 +608,7 @@ pub(crate) struct TransparentIncompatible { } #[derive(Diagnostic)] -#[diag("representation attribute is specified more than once")] +#[diag("`#[repr(..)]` attribute is specified more than once")] #[note("for consistency, only specify the representation once")] pub(crate) struct RepeatedRepr; diff --git a/tests/ui/attributes/issue-100631.rs b/tests/ui/attributes/issue-100631.rs index d496231c73026..9a30691a39ec3 100644 --- a/tests/ui/attributes/issue-100631.rs +++ b/tests/ui/attributes/issue-100631.rs @@ -2,7 +2,7 @@ // can reasonably deal with multiple attributes. // `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`. #[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084] -//~^ WARN representation attribute is specified more than once +//~^ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] #[repr(C)] enum Foo {} diff --git a/tests/ui/attributes/issue-100631.stderr b/tests/ui/attributes/issue-100631.stderr index 66e08738eb02c..0ecc19ae85b3d 100644 --- a/tests/ui/attributes/issue-100631.stderr +++ b/tests/ui/attributes/issue-100631.stderr @@ -1,4 +1,4 @@ -warning: representation attribute is specified more than once +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/issue-100631.rs:4:8 | LL | #[repr(C)] diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs index 348c9590e8b27..c013041ed4159 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.rs +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -64,7 +64,7 @@ fn t1() {} #[must_use = "some message"] //~^ ERROR unused attribute //~| WARN this was previously accepted -#[repr(C)] //~ WARN representation attribute is specified more than once +#[repr(C)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] #[repr(C)] #[non_exhaustive] #[non_exhaustive] //~ ERROR unused attribute diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 93f7a4791188f..6e4f7d23604c2 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -16,7 +16,7 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -warning: representation attribute is specified more than once +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/unused-attr-duplicate.rs:67:8 | LL | #[repr(C)] @@ -264,19 +264,6 @@ note: attribute also specified here LL | #[track_caller] | ^^^^^^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:93:5 - | -LL | #[link_name = "rust_dbg_extern_identity_u32"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:92:5 - | -LL | #[link_name = "this_does_not_exist"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - error: unused attribute --> $DIR/unused-attr-duplicate.rs:99:1 | @@ -328,13 +315,13 @@ LL | #[link_section = "__TEXT,__text"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: unused attribute - --> $DIR/unused-attr-duplicate.rs:94:5 + --> $DIR/unused-attr-duplicate.rs:93:5 | LL | #[link_name = "rust_dbg_extern_identity_u32"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:93:5 + --> $DIR/unused-attr-duplicate.rs:92:5 | LL | #[link_name = "this_does_not_exist"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/repr/conflicting-repr-hints.rs b/tests/ui/repr/conflicting-repr-hints.rs index 032f2b2e6c608..81a94aad78ff6 100644 --- a/tests/ui/repr/conflicting-repr-hints.rs +++ b/tests/ui/repr/conflicting-repr-hints.rs @@ -36,10 +36,10 @@ struct G(i32); //~ ERROR type has conflicting packed and align representation hi #[repr(packed)] struct H(i32); //~ ERROR type has conflicting packed and align representation hints -#[repr(packed, packed(2))] //~ WARN representation attribute is specified more than once +#[repr(packed, packed(2))] struct I(i32); //~ ERROR type has conflicting packed representation hints -#[repr(packed(2))] //~ WARN representation attribute is specified more than once +#[repr(packed(2))] #[repr(packed)] struct J(i32); //~ ERROR type has conflicting packed representation hints diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr index a99546b754785..8f2655fd716f1 100644 --- a/tests/ui/repr/conflicting-repr-hints.stderr +++ b/tests/ui/repr/conflicting-repr-hints.stderr @@ -17,32 +17,14 @@ LL | #[repr(u32, u64)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 -warning: representation attribute is specified more than once - --> $DIR/conflicting-repr-hints.rs:39:8 - | -LL | #[repr(packed, packed(2))] - | ^^^^^^ ^^^^^^^^^ - | - = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default - -warning: representation attribute is specified more than once - --> $DIR/conflicting-repr-hints.rs:42:8 - | -LL | #[repr(packed(2))] - | ^^^^^^^^^ -LL | #[repr(packed)] - | ^^^^^^ - | - = note: for consistency, only specify the representation once - -warning: representation attribute is specified more than once +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/conflicting-repr-hints.rs:46:8 | LL | #[repr(packed, packed(1))] | ^^^^^^ ^^^^^^^^^ | = note: for consistency, only specify the representation once + = note: `#[warn(repeated_reprs)]` on by default error[E0587]: type has conflicting packed and align representation hints --> $DIR/conflicting-repr-hints.rs:29:1 @@ -104,7 +86,7 @@ error[E0587]: type has conflicting packed and align representation hints LL | pub union U { | ^^^^^^^^^^^ -error: aborting due to 12 previous errors; 3 warnings emitted +error: aborting due to 12 previous errors; 1 warning emitted Some errors have detailed explanations: E0566, E0587, E0634. For more information about an error, try `rustc --explain E0566`. diff --git a/tests/ui/repr/repr-repeated-attrs.rs b/tests/ui/repr/repr-repeated-attrs.rs index 61e3ba05625d8..7306b9192f09e 100644 --- a/tests/ui/repr/repr-repeated-attrs.rs +++ b/tests/ui/repr/repr-repeated-attrs.rs @@ -1,32 +1,32 @@ // Tests to ensure we warn on repeated `#[repr(..)]` attributes. -#[repr(transparent, transparent)] +#[repr(transparent, transparent)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR transparent struct cannot have other repr hints #[repr(transparent)] struct SeveralTransparentReprs(*mut u8); -#[repr(transparent)] +#[repr(transparent)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR transparent struct cannot have other repr hints #[repr(transparent)] struct MultilineOnly(*mut u8); #[repr(Rust, Rust)] -//~^ WARN representation attribute is specified more than once +//~^ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] struct SeveralRustReprs(u8); #[repr(C, C)] -//~^ WARN representation attribute is specified more than once +//~^ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] #[repr(C, C, C)] struct SeveralC(u8); -#[repr(u8, u8)] //~ WARN representation attribute is specified more than once +#[repr(u8, u8)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR conflicting representation hints //~| WARN this was previously accepted enum SeveralPrimitiveRerprs { Variant, } -#[repr(C, C, u8)] //~ WARN representation attribute is specified more than once +#[repr(C, C, u8)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR conflicting representation hints //~| WARN this was previously accepted #[repr(C, u8, u8)] @@ -34,7 +34,7 @@ enum SeveralCAndPrims { Variant(u8), } -#[repr(Rust, u8, u8)] //~ WARN representation attribute is specified more than once +#[repr(Rust, u8, u8)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR conflicting representation hints //~^^ ERROR conflicting representation hints //~| WARN this was previously accepted @@ -42,7 +42,7 @@ enum RustAndPrimDisallowed { Variant(u8), } -#[repr(u8, u8)] //~ WARN representation attribute is specified more than once +#[repr(u8, u8)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR conflicting representation hints //~| WARN this was previously accepted #[repr(u16)] @@ -58,7 +58,7 @@ enum CWithIntsCausesFCW1 { B, } -#[repr(C, C, u8, u8, u8)] //~ WARN representation attribute is specified more than once +#[repr(C, C, u8, u8, u8)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR conflicting representation hints //~| WARN this was previously accepted enum CWithIntsCausesFCW2 { diff --git a/tests/ui/repr/repr-repeated-attrs.stderr b/tests/ui/repr/repr-repeated-attrs.stderr index 57af8ec804d76..a0b8b1d7da3cc 100644 --- a/tests/ui/repr/repr-repeated-attrs.stderr +++ b/tests/ui/repr/repr-repeated-attrs.stderr @@ -1,3 +1,15 @@ +warning: `#[repr(..)]` attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:3:8 + | +LL | #[repr(transparent, transparent)] + | ^^^^^^^^^^^ ^^^^^^^^^^^ +LL | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ + | + = note: for consistency, only specify the representation once + = note: `#[warn(repeated_reprs)]` on by default + error[E0692]: transparent struct cannot have other repr hints --> $DIR/repr-repeated-attrs.rs:3:8 | @@ -7,6 +19,17 @@ LL | LL | #[repr(transparent)] | ^^^^^^^^^^^ +warning: `#[repr(..)]` attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:8:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +LL | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ + | + = note: for consistency, only specify the representation once + error[E0692]: transparent struct cannot have other repr hints --> $DIR/repr-repeated-attrs.rs:8:8 | @@ -16,16 +39,15 @@ LL | LL | #[repr(transparent)] | ^^^^^^^^^^^ -warning: representation attribute is specified more than once +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/repr-repeated-attrs.rs:13:8 | LL | #[repr(Rust, Rust)] | ^^^^ ^^^^ | = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default -warning: representation attribute is specified more than once +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/repr-repeated-attrs.rs:17:8 | LL | #[repr(C, C)] @@ -36,25 +58,25 @@ LL | #[repr(C, C, C)] | = note: for consistency, only specify the representation once -error[E0566]: conflicting representation hints +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/repr-repeated-attrs.rs:22:8 | LL | #[repr(u8, u8)] | ^^ ^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #68585 - = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default + = note: for consistency, only specify the representation once -warning: representation attribute is specified more than once +error[E0566]: conflicting representation hints --> $DIR/repr-repeated-attrs.rs:22:8 | LL | #[repr(u8, u8)] | ^^ ^^ | - = note: for consistency, only specify the representation once + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default -error[E0566]: conflicting representation hints +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/repr-repeated-attrs.rs:29:8 | LL | #[repr(C, C, u8)] @@ -63,10 +85,9 @@ LL | #[repr(C, C, u8)] LL | #[repr(C, u8, u8)] | ^ ^^ ^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #68585 + = note: for consistency, only specify the representation once -warning: representation attribute is specified more than once +error[E0566]: conflicting representation hints --> $DIR/repr-repeated-attrs.rs:29:8 | LL | #[repr(C, C, u8)] @@ -75,6 +96,15 @@ LL | #[repr(C, C, u8)] LL | #[repr(C, u8, u8)] | ^ ^^ ^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +warning: `#[repr(..)]` attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:37:14 + | +LL | #[repr(Rust, u8, u8)] + | ^^ ^^ + | = note: for consistency, only specify the representation once error[E0566]: conflicting representation hints @@ -92,11 +122,11 @@ LL | #[repr(Rust, u8, u8)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 -warning: representation attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:37:8 +warning: `#[repr(..)]` attribute is specified more than once + --> $DIR/repr-repeated-attrs.rs:45:8 | -LL | #[repr(Rust, u8, u8)] - | ^^^^ ^^ ^^ +LL | #[repr(u8, u8)] + | ^^ ^^ | = note: for consistency, only specify the representation once @@ -112,17 +142,6 @@ LL | #[repr(u16)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 -warning: representation attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:45:8 - | -LL | #[repr(u8, u8)] - | ^^ ^^ -... -LL | #[repr(u16)] - | ^^^ - | - = note: for consistency, only specify the representation once - error[E0566]: conflicting representation hints --> $DIR/repr-repeated-attrs.rs:53:8 | @@ -132,24 +151,24 @@ LL | #[repr(C, u8)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #68585 -error[E0566]: conflicting representation hints +warning: `#[repr(..)]` attribute is specified more than once --> $DIR/repr-repeated-attrs.rs:61:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #68585 + = note: for consistency, only specify the representation once -warning: representation attribute is specified more than once +error[E0566]: conflicting representation hints --> $DIR/repr-repeated-attrs.rs:61:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ | - = note: for consistency, only specify the representation once + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 -error: aborting due to 9 previous errors; 7 warnings emitted +error: aborting due to 9 previous errors; 9 warnings emitted Some errors have detailed explanations: E0566, E0692. For more information about an error, try `rustc --explain E0566`. diff --git a/tests/ui/structs-enums/align-enum.rs b/tests/ui/structs-enums/align-enum.rs index a635af7352afe..ff80a19211cda 100644 --- a/tests/ui/structs-enums/align-enum.rs +++ b/tests/ui/structs-enums/align-enum.rs @@ -11,7 +11,7 @@ enum Align16 { } // Raise alignment by maximum -#[repr(align(1), align(16))] //~ WARN representation attribute is specified more than once +#[repr(align(1), align(16))] #[repr(align(32))] #[repr(align(4))] enum Align32 { diff --git a/tests/ui/structs-enums/align-enum.stderr b/tests/ui/structs-enums/align-enum.stderr deleted file mode 100644 index 9b8c9842f81df..0000000000000 --- a/tests/ui/structs-enums/align-enum.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: representation attribute is specified more than once - --> $DIR/align-enum.rs:14:8 - | -LL | #[repr(align(1), align(16))] - | ^^^^^^^^ ^^^^^^^^^ -LL | #[repr(align(32))] - | ^^^^^^^^^ -LL | #[repr(align(4))] - | ^^^^^^^^ - | - = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/structs-enums/align-struct.rs b/tests/ui/structs-enums/align-struct.rs index 2d1ebf6731a62..3d8dad6e324e3 100644 --- a/tests/ui/structs-enums/align-struct.rs +++ b/tests/ui/structs-enums/align-struct.rs @@ -13,7 +13,7 @@ struct Align16(i32); struct Align1(i32); // Multiple attributes take the max -#[repr(align(4))] //~ WARN representation attribute is specified more than once +#[repr(align(4))] #[repr(align(16))] #[repr(align(8))] struct AlignMany(i32); diff --git a/tests/ui/structs-enums/align-struct.stderr b/tests/ui/structs-enums/align-struct.stderr deleted file mode 100644 index f54e9cd14cd8b..0000000000000 --- a/tests/ui/structs-enums/align-struct.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: representation attribute is specified more than once - --> $DIR/align-struct.rs:16:8 - | -LL | #[repr(align(4))] - | ^^^^^^^^ -LL | #[repr(align(16))] - | ^^^^^^^^^ -LL | #[repr(align(8))] - | ^^^^^^^^ - | - = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default - -warning: 1 warning emitted - From e99f23fec0b37494a9361b02fe509997896c5e37 Mon Sep 17 00:00:00 2001 From: Charlotte Ausel Date: Mon, 24 Aug 2026 13:07:15 +0100 Subject: [PATCH 15/16] add to unused group --- compiler/rustc_lint/src/lib.rs | 3 +- compiler/rustc_lint_defs/src/builtin.rs | 1 + tests/ui/attributes/issue-100631.rs | 1 + tests/ui/attributes/issue-100631.stderr | 6 +-- ...-dont-override-forbid-in-same-scope.stderr | 18 +++++++ tests/ui/lint/outer-forbid.stderr | 18 +++++++ tests/ui/lint/unused/unused-attr-duplicate.rs | 2 +- .../lint/unused/unused-attr-duplicate.stderr | 2 +- tests/ui/repr/conflicting-repr-hints.rs | 1 + tests/ui/repr/conflicting-repr-hints.stderr | 32 ++++++------ tests/ui/repr/repr-repeated-attrs.rs | 1 + tests/ui/repr/repr-repeated-attrs.stderr | 50 +++++++++---------- 12 files changed, 88 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 852f1cfda5168..1a392ae1c05da 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -367,7 +367,8 @@ fn register_builtins(store: &mut LintStore) { UNUSED_PARENS, UNUSED_BRACES, REDUNDANT_SEMICOLONS, - MAP_UNIT_FN + MAP_UNIT_FN, + REPEATED_REPRS ); add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 11cdbea3c426a..af5db6117f7b5 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -95,6 +95,7 @@ pub mod hardwired { REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE, RENAMED_AND_REMOVED_LINTS, + REPEATED_REPRS, REPR_C_ENUMS_LARGER_THAN_INT, RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS, RTSAN_NONBLOCKING_ASYNC, diff --git a/tests/ui/attributes/issue-100631.rs b/tests/ui/attributes/issue-100631.rs index 9a30691a39ec3..09b34ebfe7a2c 100644 --- a/tests/ui/attributes/issue-100631.rs +++ b/tests/ui/attributes/issue-100631.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -W repeated-reprs // issue #100631, make sure `TyCtxt::get_attr` only called by case that compiler // can reasonably deal with multiple attributes. // `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`. diff --git a/tests/ui/attributes/issue-100631.stderr b/tests/ui/attributes/issue-100631.stderr index 0ecc19ae85b3d..62d82c9b31335 100644 --- a/tests/ui/attributes/issue-100631.stderr +++ b/tests/ui/attributes/issue-100631.stderr @@ -1,5 +1,5 @@ warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/issue-100631.rs:4:8 + --> $DIR/issue-100631.rs:5:8 | LL | #[repr(C)] | ^ @@ -8,10 +8,10 @@ LL | #[repr(C)] | ^ | = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default + = note: requested on the command line with `-W repeated-reprs` error[E0084]: unsupported representation for zero-variant enum - --> $DIR/issue-100631.rs:4:8 + --> $DIR/issue-100631.rs:5:8 | LL | #[repr(C)] | ^ diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr index f40fb73acbb8b..b0eb5636d0479 100644 --- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -449,3 +449,21 @@ note: the lint level is defined here LL | #![forbid(forbidden_lint_groups)] | ^^^^^^^^^^^^^^^^^^^^^ +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/outer-forbid.stderr b/tests/ui/lint/outer-forbid.stderr index abe5959176d4a..b2d7ad6c2aabc 100644 --- a/tests/ui/lint/outer-forbid.stderr +++ b/tests/ui/lint/outer-forbid.stderr @@ -489,3 +489,21 @@ note: the lint level is defined here LL | #![forbid(forbidden_lint_groups)] | ^^^^^^^^^^^^^^^^^^^^^ +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs index c013041ed4159..c62fc6036f60f 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.rs +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -1,6 +1,6 @@ // Tests for repeating attribute warnings. //@ aux-build:lint_unused_extern_crate.rs -//@ compile-flags:--test +//@ compile-flags:--test -W repeated-reprs // Not tested due to extra requirements: // - panic_handler: needs extra setup // - target_feature: platform-specific diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 6e4f7d23604c2..feb1a79bf9b92 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -25,7 +25,7 @@ LL | #[repr(C)] | ^ | = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default + = note: requested on the command line with `-W repeated-reprs` error: unused attribute --> $DIR/unused-attr-duplicate.rs:14:1 diff --git a/tests/ui/repr/conflicting-repr-hints.rs b/tests/ui/repr/conflicting-repr-hints.rs index 81a94aad78ff6..6a265e13ad93d 100644 --- a/tests/ui/repr/conflicting-repr-hints.rs +++ b/tests/ui/repr/conflicting-repr-hints.rs @@ -1,3 +1,4 @@ +//@ compile-flags: -W repeated-reprs #![allow(dead_code)] #[repr(C)] diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr index 8f2655fd716f1..2a81610e85f99 100644 --- a/tests/ui/repr/conflicting-repr-hints.stderr +++ b/tests/ui/repr/conflicting-repr-hints.stderr @@ -1,5 +1,5 @@ error[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:13:8 + --> $DIR/conflicting-repr-hints.rs:14:8 | LL | #[repr(C, u64)] | ^ ^^^ @@ -9,7 +9,7 @@ LL | #[repr(C, u64)] = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default error[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:19:8 + --> $DIR/conflicting-repr-hints.rs:20:8 | LL | #[repr(u32, u64)] | ^^^ ^^^ @@ -18,70 +18,70 @@ LL | #[repr(u32, u64)] = note: for more information, see issue #68585 warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/conflicting-repr-hints.rs:46:8 + --> $DIR/conflicting-repr-hints.rs:47:8 | LL | #[repr(packed, packed(1))] | ^^^^^^ ^^^^^^^^^ | = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default + = note: requested on the command line with `-W repeated-reprs` error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:29:1 + --> $DIR/conflicting-repr-hints.rs:30:1 | LL | struct F(i32); | ^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:33:1 + --> $DIR/conflicting-repr-hints.rs:34:1 | LL | struct G(i32); | ^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:37:1 + --> $DIR/conflicting-repr-hints.rs:38:1 | LL | struct H(i32); | ^^^^^^^^ error[E0634]: type has conflicting packed representation hints - --> $DIR/conflicting-repr-hints.rs:40:1 + --> $DIR/conflicting-repr-hints.rs:41:1 | LL | struct I(i32); | ^^^^^^^^ error[E0634]: type has conflicting packed representation hints - --> $DIR/conflicting-repr-hints.rs:44:1 + --> $DIR/conflicting-repr-hints.rs:45:1 | LL | struct J(i32); | ^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:50:1 + --> $DIR/conflicting-repr-hints.rs:51:1 | LL | union X { | ^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:57:1 + --> $DIR/conflicting-repr-hints.rs:58:1 | LL | union Y { | ^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:64:1 + --> $DIR/conflicting-repr-hints.rs:65:1 | LL | union Z { | ^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:70:1 + --> $DIR/conflicting-repr-hints.rs:71:1 | LL | pub struct S(u16); | ^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:73:1 + --> $DIR/conflicting-repr-hints.rs:74:1 | LL | pub union U { | ^^^^^^^^^^^ @@ -92,7 +92,7 @@ Some errors have detailed explanations: E0566, E0587, E0634. For more information about an error, try `rustc --explain E0566`. Future incompatibility report: Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:13:8 + --> $DIR/conflicting-repr-hints.rs:14:8 | LL | #[repr(C, u64)] | ^ ^^^ @@ -103,7 +103,7 @@ LL | #[repr(C, u64)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:19:8 + --> $DIR/conflicting-repr-hints.rs:20:8 | LL | #[repr(u32, u64)] | ^^^ ^^^ diff --git a/tests/ui/repr/repr-repeated-attrs.rs b/tests/ui/repr/repr-repeated-attrs.rs index 7306b9192f09e..122eb9b7485ef 100644 --- a/tests/ui/repr/repr-repeated-attrs.rs +++ b/tests/ui/repr/repr-repeated-attrs.rs @@ -1,4 +1,5 @@ // Tests to ensure we warn on repeated `#[repr(..)]` attributes. +//@ compile-flags: -W repeated-reprs #[repr(transparent, transparent)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs] //~^ ERROR transparent struct cannot have other repr hints diff --git a/tests/ui/repr/repr-repeated-attrs.stderr b/tests/ui/repr/repr-repeated-attrs.stderr index a0b8b1d7da3cc..a1e54f6218889 100644 --- a/tests/ui/repr/repr-repeated-attrs.stderr +++ b/tests/ui/repr/repr-repeated-attrs.stderr @@ -1,5 +1,5 @@ warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:3:8 + --> $DIR/repr-repeated-attrs.rs:4:8 | LL | #[repr(transparent, transparent)] | ^^^^^^^^^^^ ^^^^^^^^^^^ @@ -8,10 +8,10 @@ LL | #[repr(transparent)] | ^^^^^^^^^^^ | = note: for consistency, only specify the representation once - = note: `#[warn(repeated_reprs)]` on by default + = note: requested on the command line with `-W repeated-reprs` error[E0692]: transparent struct cannot have other repr hints - --> $DIR/repr-repeated-attrs.rs:3:8 + --> $DIR/repr-repeated-attrs.rs:4:8 | LL | #[repr(transparent, transparent)] | ^^^^^^^^^^^ ^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | #[repr(transparent)] | ^^^^^^^^^^^ warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:8:8 + --> $DIR/repr-repeated-attrs.rs:9:8 | LL | #[repr(transparent)] | ^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | #[repr(transparent)] = note: for consistency, only specify the representation once error[E0692]: transparent struct cannot have other repr hints - --> $DIR/repr-repeated-attrs.rs:8:8 + --> $DIR/repr-repeated-attrs.rs:9:8 | LL | #[repr(transparent)] | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | #[repr(transparent)] | ^^^^^^^^^^^ warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:13:8 + --> $DIR/repr-repeated-attrs.rs:14:8 | LL | #[repr(Rust, Rust)] | ^^^^ ^^^^ @@ -48,7 +48,7 @@ LL | #[repr(Rust, Rust)] = note: for consistency, only specify the representation once warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:17:8 + --> $DIR/repr-repeated-attrs.rs:18:8 | LL | #[repr(C, C)] | ^ ^ @@ -59,7 +59,7 @@ LL | #[repr(C, C, C)] = note: for consistency, only specify the representation once warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:22:8 + --> $DIR/repr-repeated-attrs.rs:23:8 | LL | #[repr(u8, u8)] | ^^ ^^ @@ -67,7 +67,7 @@ LL | #[repr(u8, u8)] = note: for consistency, only specify the representation once error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:22:8 + --> $DIR/repr-repeated-attrs.rs:23:8 | LL | #[repr(u8, u8)] | ^^ ^^ @@ -77,7 +77,7 @@ LL | #[repr(u8, u8)] = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:29:8 + --> $DIR/repr-repeated-attrs.rs:30:8 | LL | #[repr(C, C, u8)] | ^ ^ ^^ @@ -88,7 +88,7 @@ LL | #[repr(C, u8, u8)] = note: for consistency, only specify the representation once error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:29:8 + --> $DIR/repr-repeated-attrs.rs:30:8 | LL | #[repr(C, C, u8)] | ^ ^ ^^ @@ -100,7 +100,7 @@ LL | #[repr(C, u8, u8)] = note: for more information, see issue #68585 warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:37:14 + --> $DIR/repr-repeated-attrs.rs:38:14 | LL | #[repr(Rust, u8, u8)] | ^^ ^^ @@ -108,13 +108,13 @@ LL | #[repr(Rust, u8, u8)] = note: for consistency, only specify the representation once error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:37:8 + --> $DIR/repr-repeated-attrs.rs:38:8 | LL | #[repr(Rust, u8, u8)] | ^^^^ ^^ ^^ error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:37:8 + --> $DIR/repr-repeated-attrs.rs:38:8 | LL | #[repr(Rust, u8, u8)] | ^^^^ ^^ ^^ @@ -123,7 +123,7 @@ LL | #[repr(Rust, u8, u8)] = note: for more information, see issue #68585 warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:45:8 + --> $DIR/repr-repeated-attrs.rs:46:8 | LL | #[repr(u8, u8)] | ^^ ^^ @@ -131,7 +131,7 @@ LL | #[repr(u8, u8)] = note: for consistency, only specify the representation once error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:45:8 + --> $DIR/repr-repeated-attrs.rs:46:8 | LL | #[repr(u8, u8)] | ^^ ^^ @@ -143,7 +143,7 @@ LL | #[repr(u16)] = note: for more information, see issue #68585 error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:53:8 + --> $DIR/repr-repeated-attrs.rs:54:8 | LL | #[repr(C, u8)] | ^ ^^ @@ -152,7 +152,7 @@ LL | #[repr(C, u8)] = note: for more information, see issue #68585 warning: `#[repr(..)]` attribute is specified more than once - --> $DIR/repr-repeated-attrs.rs:61:8 + --> $DIR/repr-repeated-attrs.rs:62:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ @@ -160,7 +160,7 @@ LL | #[repr(C, C, u8, u8, u8)] = note: for consistency, only specify the representation once error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:61:8 + --> $DIR/repr-repeated-attrs.rs:62:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ @@ -174,7 +174,7 @@ Some errors have detailed explanations: E0566, E0692. For more information about an error, try `rustc --explain E0566`. Future incompatibility report: Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:22:8 + --> $DIR/repr-repeated-attrs.rs:23:8 | LL | #[repr(u8, u8)] | ^^ ^^ @@ -185,7 +185,7 @@ LL | #[repr(u8, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:29:8 + --> $DIR/repr-repeated-attrs.rs:30:8 | LL | #[repr(C, C, u8)] | ^ ^ ^^ @@ -199,7 +199,7 @@ LL | #[repr(C, u8, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:37:8 + --> $DIR/repr-repeated-attrs.rs:38:8 | LL | #[repr(Rust, u8, u8)] | ^^^^ ^^ ^^ @@ -210,7 +210,7 @@ LL | #[repr(Rust, u8, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:45:8 + --> $DIR/repr-repeated-attrs.rs:46:8 | LL | #[repr(u8, u8)] | ^^ ^^ @@ -224,7 +224,7 @@ LL | #[repr(u16)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:53:8 + --> $DIR/repr-repeated-attrs.rs:54:8 | LL | #[repr(C, u8)] | ^ ^^ @@ -235,7 +235,7 @@ LL | #[repr(C, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/repr-repeated-attrs.rs:61:8 + --> $DIR/repr-repeated-attrs.rs:62:8 | LL | #[repr(C, C, u8, u8, u8)] | ^ ^ ^^ ^^ ^^ From 8de399ac7b7cce3314f4f7e2cd2e1285b1608e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 26 Aug 2026 04:19:51 +0200 Subject: [PATCH 16/16] Remove dead parse error recovery (underscores in expressions) --- compiler/rustc_parse/src/parser/expr.rs | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 2fa36d7ce059e..7227c814ce9d6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -85,30 +85,9 @@ impl<'a> Parser<'a> { self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value }) } - fn parse_expr_catch_underscore( - &mut self, - restrictions: Restrictions, - ) -> PResult<'a, Box> { - match self.parse_expr_res(restrictions) { - Ok(expr) => Ok(expr), - Err(err) => match self.token.ident() { - Some((Ident { name: kw::Underscore, .. }, IdentIsRaw::No)) - if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) => - { - // Special-case handling of `foo(_, _, _)` - let guar = err.emit(); - self.bump(); - Ok(self.mk_expr(self.prev_token.span, ExprKind::Err(guar))) - } - _ => Err(err), - }, - } - } - /// Parses a sequence of expressions delimited by parentheses. fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec>> { - self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty())) - .map(|(r, _)| r) + self.parse_paren_comma_seq(Self::parse_expr).map(|(r, _)| r) } /// Parses an expression, subject to the given restrictions. @@ -1644,7 +1623,7 @@ impl<'a> Parser<'a> { let (es, trailing_comma) = match self.parse_seq_to_end( exp!(CloseParen), SeqSep::trailing_allowed(exp!(Comma)), - |p| p.parse_expr_catch_underscore(restrictions.intersection(Restrictions::ALLOW_LET)), + |p| p.parse_expr_res(restrictions.intersection(Restrictions::ALLOW_LET)), ) { Ok(x) => x, Err(err) => {