From 54569c6fc70459916b3c894519c502d700436405 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 23 May 2026 16:58:04 -0400 Subject: [PATCH 01/15] Make hint::cold_path #[cold] so that it works even if the MIR inliner can't inline it --- library/core/src/hint.rs | 3 + .../hint/cold_path-target_feature.rs | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/codegen-llvm/hint/cold_path-target_feature.rs diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index a8e01e6e78b4b..90326e649058b 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -778,6 +778,9 @@ pub const fn unlikely(b: bool) -> bool { #[stable(feature = "cold_path", since = "1.95.0")] #[rustc_const_stable(feature = "cold_path", since = "1.95.0")] #[inline(always)] +// Even if for some reason the cold_path intrinsic is not visible to codegen, the coldness will +// ensure that branches this is in are still known to be cold. +#[cold] pub const fn cold_path() { crate::intrinsics::cold_path() } diff --git a/tests/codegen-llvm/hint/cold_path-target_feature.rs b/tests/codegen-llvm/hint/cold_path-target_feature.rs new file mode 100644 index 0000000000000..9e06fd0ceafa1 --- /dev/null +++ b/tests/codegen-llvm/hint/cold_path-target_feature.rs @@ -0,0 +1,56 @@ +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +#![crate_type = "lib"] + +// This test checks that hint::cold_path still works in #[target_feature] functions. + +use std::hint::cold_path; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test1(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @test1( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM:[0-9]+]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +#[no_mangle] +#[target_feature(enable = "sse2")] +pub fn with_target_feature(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @with_target_feature( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} From bcf900133d46083076c92c435d6410241fac1381 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Sun, 24 May 2026 19:52:36 +0200 Subject: [PATCH 02/15] feat: rename debug-info-for-profiling switch --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 ++-- ...debug_info_for_profiling.md => debuginfo_for_profiling.md} | 4 ++-- .../unstable-book/src/compiler-flags/profile_sample_use.md | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename src/doc/unstable-book/src/compiler-flags/{debug_info_for_profiling.md => debuginfo_for_profiling.md} (93%) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7b22ac231df1c..40236f2896e34 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -180,7 +180,7 @@ impl ModuleConfig { ), pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None), pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None), - debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling, + debug_info_for_profiling: sess.opts.unstable_opts.debuginfo_for_profiling, instrument_coverage: if_regular!(sess.instrument_coverage(), false), sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0837e7767605c..0498d835df5f5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -782,8 +782,8 @@ fn test_unstable_options_tracking_hash() { ); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); - tracked!(debug_info_for_profiling, true); tracked!(debug_info_type_line_numbers, true); + tracked!(debuginfo_for_profiling, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); tracked!(dep_info_omit_d_target, true); tracked!(direct_access_external_data, Some(true)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index aa9331ee8f659..bbccff73fb34e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2252,12 +2252,12 @@ options! { "inject the given attribute in the crate"), cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], "threshold to allow cross crate inlining of functions"), - debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], - "emit discriminators and other data necessary for AutoFDO"), debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED], "emit type and line information for additional data types (default: no)"), debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], "compress debug info sections (none, zlib, zstd, default: none)"), + debuginfo_for_profiling: bool = (false, parse_bool, [TRACKED], + "emit discriminators and other data necessary for AutoFDO"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), default_visibility: Option = (None, parse_opt_symbol_visibility, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md similarity index 93% rename from src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md rename to src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md index ee72b6adf8e9f..d25cdcaeb7427 100644 --- a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md +++ b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md @@ -1,4 +1,4 @@ -# `debug-info-for-profiling` +# `debuginfo-for-profiling` --- @@ -22,7 +22,7 @@ external tool `create_llvm_prof` from [this repository] must be used. Given a Rust file `main.rs`, we can produce an optimized binary as follows: ```shell -rustc -O -Zdebug-info-for-profiling main.rs -o main +rustc -O -Zdebuginfo-for-profiling main.rs -o main perf record -b ./main create_llvm_prof --binary=main --out=code.prof rustc -O -Zprofile-sample-use=code.prof main.rs -o main2 diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md index 2dd1f6f8e1a3a..a9bcca3e1522a 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md +++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md @@ -4,7 +4,7 @@ `-Zprofile-sample-use=code.prof` directs `rustc` to use the profile `code.prof` as a source for Automatic Feedback Directed Optimization (AFDO). -See the documentation of [`-Zdebug-info-for-profiling`] for more information +See the documentation of [`-Zdebuginfo-for-profiling`] for more information on using AFDO. -[`-Zdebug-info-for-profiling`]: debug_info_for_profiling.html +[`-Zdebuginfo-for-profiling`]: debuginfo_for_profiling.html From fe17ed58e960f9fa2195590c4b25457f2b2d9e9b Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Sun, 10 May 2026 22:06:26 +0200 Subject: [PATCH 03/15] feat: add tests for `debuginfo-for-profiling` - the test was ported from this commit: https://github.com/llvm/llvm-project/commit/300921157385c5f6e0884537510c3ce1f336cd8c --- .../assembly-llvm/debuginfo-for-profiling.rs | 56 +++++++++++++++++++ tests/codegen-llvm/debuginfo-for-profiling.rs | 45 +++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 tests/assembly-llvm/debuginfo-for-profiling.rs create mode 100644 tests/codegen-llvm/debuginfo-for-profiling.rs diff --git a/tests/assembly-llvm/debuginfo-for-profiling.rs b/tests/assembly-llvm/debuginfo-for-profiling.rs new file mode 100644 index 0000000000000..6431142e7b621 --- /dev/null +++ b/tests/assembly-llvm/debuginfo-for-profiling.rs @@ -0,0 +1,56 @@ +// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`: +// - 0 discriminators are emitted without the flag in the test below +// - at least 1 discriminator is emitted with the flag in the test below. +// Actual count depends on the target +// +// +//@ add-minicore +//@ revisions: DEFAULT-X86 DEFAULT-AARCH64 DEBUGINFO-X86 DEBUGINFO-AARCH64 +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only +//@ [DEFAULT-X86] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [DEFAULT-X86] needs-llvm-components: x86 +//@ [DEFAULT-AARCH64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [DEFAULT-AARCH64] needs-llvm-components: aarch64 +//@ [DEBUGINFO-X86] compile-flags: -Zdebuginfo-for-profiling --target=x86_64-unknown-linux-gnu +//@ [DEBUGINFO-X86] needs-llvm-components: x86 +//@ [DEBUGINFO-AARCH64] compile-flags: -Zdebuginfo-for-profiling --target=aarch64-unknown-linux-gnu +//@ [DEBUGINFO-AARCH64] needs-llvm-components: aarch64 +// DEFAULT-X86-NOT: discriminator +// DEFAULT-AARCH64-NOT: discriminator +// DEBUGINFO-X86-COUNT-1: discriminator +// DEBUGINFO-AARCH64-COUNT-1: discriminator + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn add(_x: i32, _y: i32) -> i32; + fn mul(_x: i32, _y: i32) -> i32; + fn compute(_x: i32) -> i32; + fn cond() -> bool; +} + +#[no_mangle] +pub fn f(limit: i32) -> i32 { + unsafe { + let mut sum = 0; + let mut i = 1; + + while cond() { + if cond() { + sum = add(sum, compute(i)); + } else { + sum = add(sum, mul(compute(i), 2)); + } + i = add(i, 1); + } + + sum + } +} diff --git a/tests/codegen-llvm/debuginfo-for-profiling.rs b/tests/codegen-llvm/debuginfo-for-profiling.rs new file mode 100644 index 0000000000000..f7e401415ac7e --- /dev/null +++ b/tests/codegen-llvm/debuginfo-for-profiling.rs @@ -0,0 +1,45 @@ +// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`: +// - 0 discriminators are emitted without the flag in the test below +// - at least 1 discriminator is emitted with the flag in the test below +// +// +//@ add-minicore +//@ revisions: DEFAULT DEBUGINFO +//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only +//@ [DEBUGINFO] compile-flags: -Zdebuginfo-for-profiling +// DEFAULT-NOT: discriminator +// DEBUGINFO-COUNT-1: discriminator + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn add(_x: i32, _y: i32) -> i32; + fn mul(_x: i32, _y: i32) -> i32; + fn compute(_x: i32) -> i32; + fn cond() -> bool; +} + +#[no_mangle] +pub fn f(limit: i32) -> i32 { + unsafe { + let mut sum = 0; + let mut i = 1; + + while cond() { + if cond() { + sum = add(sum, compute(i)); + } else { + sum = add(sum, mul(compute(i), 2)); + } + i = add(i, 1); + } + + sum + } +} From 1f5a5a2b690f13da8021a5751dc6279a868ba884 Mon Sep 17 00:00:00 2001 From: lcian <17258265+lcian@users.noreply.github.com> Date: Fri, 29 May 2026 15:54:48 +0000 Subject: [PATCH 04/15] rustdoc: correctly propagate cfgs for glob reexports * rustdoc: correctly propagate cfgs for glob reexports * address review feedback, add a comment explaining the test * empty commit to trigger CI * empty commit to trigger CI * fix sorting of features in tests * assert contents of index.html --- src/librustdoc/clean/mod.rs | 2 +- .../glob-reexport-feature-combination.rs | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cf6deebe8e1d7..901a7fd340afe 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -243,8 +243,8 @@ fn generate_item_with_correct_attrs( ) || (is_glob_import(tcx, import_id) && (cx.document_hidden() || !tcx.is_doc_hidden(def_id))) || macro_reexport_is_inline(tcx, import_id, def_id); - attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); is_inline = is_inline || import_is_inline; + attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); } let keep_target_cfg = is_inline || matches!(kind, ItemKind::TypeAliasItem(..)); add_without_unwanted_attributes(&mut attrs, target_attrs, keep_target_cfg, None); diff --git a/tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs b/tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs new file mode 100644 index 0000000000000..33b2fe94c138a --- /dev/null +++ b/tests/rustdoc-html/reexport/glob-reexport-feature-combination.rs @@ -0,0 +1,67 @@ +// This test ensures that `cfg`s are correctly propagated for re-export chains +// where the outermost is a glob re-export. + +#![crate_name = "foo"] +#![feature(doc_cfg)] + +//@ has 'foo/index.html' +//@ count - '//*[@class="item-table"]/dt' 3 + +//@ has 'foo/index.html' +//@ has - '//dt/a[@title="struct foo::A"]/../*[@class="stab portability"]' 'Non-bar and non-foo' + +//@ has 'foo/struct.A.html' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available on non-crate feature bar and non-crate feature foo only.' + +mod a { + mod inner { + pub struct A {} + } + #[cfg(not(feature = "bar"))] + pub use self::inner::A; +} +#[cfg(not(feature = "foo"))] +pub use a::*; + +//@ has 'foo/index.html' +//@ has - '//dt/a[@title="struct foo::B"]/../*[@class="stab portability"]' 'Non-bar and non-baz and non-foo' + +//@ has 'foo/struct.B.html' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available on non-crate feature bar and non-crate feature baz and non-crate feature foo only.' + +mod b { + mod inner { + mod innermost { + pub struct B {} + } + #[cfg(not(feature = "baz"))] + pub use self::innermost::B; + } + #[cfg(not(feature = "bar"))] + pub use self::inner::*; +} +#[cfg(not(feature = "foo"))] +pub use b::*; + +//@ has 'foo/index.html' +//@ has - '//dt/a[@title="struct foo::C"]/../*[@class="stab portability"]' 'Non-bar and non-baz and non-foo' + +//@ has 'foo/struct.C.html' +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ +// 'Available on non-crate feature bar and non-crate feature baz and non-crate feature foo only.' + +mod c { + mod inner { + mod innermost { + #[cfg(not(feature = "baz"))] + pub struct C {} + } + pub use self::innermost::*; + } + #[cfg(not(feature = "bar"))] + pub use self::inner::*; +} +#[cfg(not(feature = "foo"))] +pub use c::*; From 525723dfa390e7b74463d43855d49888ad3e5597 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 29 May 2026 21:21:45 +0200 Subject: [PATCH 05/15] Change `expected_identifier` from error code E0539 to the more specific E0565 --- .../src/session_diagnostics.rs | 1 + tests/ui/attributes/invalid-macro-use.stderr | 4 +- tests/ui/cfg/cfg-path-error.stderr | 10 +-- tests/ui/cfg/cfg-target-compact-errors.stderr | 7 +- tests/ui/cfg/path-kw-as-cfg-pred.stderr | 66 +++++++++---------- .../cfg-attr-syntax-validation.stderr | 6 +- .../cfg_attr-attr-syntax-validation.stderr | 6 +- tests/ui/link-native-libs/issue-43925.stderr | 6 +- .../link-attr-validation-late.stderr | 2 +- tests/ui/macros/cfg.stderr | 5 +- tests/ui/macros/cfg_select.rs | 4 +- tests/ui/macros/cfg_select.stderr | 6 +- tests/ui/proc-macro/attribute.stderr | 10 +-- tests/ui/tool-attributes/invalid-tool.stderr | 4 +- .../tool-attributes/nested-disallowed.stderr | 4 +- 15 files changed, 72 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index ea5c9077dcde6..79235e4fba6ad 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -849,6 +849,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { } AttributeParseErrorReason::ExpectedIdentifier => { diag.span_label(self.span, "expected a valid identifier here"); + diag.code(E0565); } } diff --git a/tests/ui/attributes/invalid-macro-use.stderr b/tests/ui/attributes/invalid-macro-use.stderr index fe235ab209f33..f02c77bf327e7 100644 --- a/tests/ui/attributes/invalid-macro-use.stderr +++ b/tests/ui/attributes/invalid-macro-use.stderr @@ -28,7 +28,7 @@ LL - #[macro_use = 5] LL + #[macro_use] | -error[E0539]: malformed `macro_use` attribute input +error[E0565]: malformed `macro_use` attribute input --> $DIR/invalid-macro-use.rs:10:1 | LL | #[macro_use(5)] @@ -82,7 +82,7 @@ LL - #[macro_use(a(b))] LL + #[macro_use] | -error[E0539]: malformed `macro_use` attribute input +error[E0565]: malformed `macro_use` attribute input --> $DIR/invalid-macro-use.rs:28:1 | LL | #[macro_use(a::b)] diff --git a/tests/ui/cfg/cfg-path-error.stderr b/tests/ui/cfg/cfg-path-error.stderr index 6f4d6b6ab1d5d..8f5ff3f025892 100644 --- a/tests/ui/cfg/cfg-path-error.stderr +++ b/tests/ui/cfg/cfg-path-error.stderr @@ -1,4 +1,4 @@ -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-path-error.rs:6:1 | LL | #[cfg(any(foo, foo::bar))] @@ -13,7 +13,7 @@ LL - #[cfg(any(foo, foo::bar))] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-path-error.rs:12:1 | LL | #[cfg(any(foo::bar, foo))] @@ -28,7 +28,7 @@ LL - #[cfg(any(foo::bar, foo))] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-path-error.rs:18:1 | LL | #[cfg(all(foo, foo::bar))] @@ -43,7 +43,7 @@ LL - #[cfg(all(foo, foo::bar))] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-path-error.rs:24:1 | LL | #[cfg(all(foo::bar, foo))] @@ -60,4 +60,4 @@ LL + #[cfg(predicate)] error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0539`. +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/cfg/cfg-target-compact-errors.stderr b/tests/ui/cfg/cfg-target-compact-errors.stderr index a228e473e6032..7fb4fa4d49bf0 100644 --- a/tests/ui/cfg/cfg-target-compact-errors.stderr +++ b/tests/ui/cfg/cfg-target-compact-errors.stderr @@ -1,4 +1,4 @@ -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-target-compact-errors.rs:5:1 | LL | #[cfg(target(o::o))] @@ -73,7 +73,7 @@ LL - #[cfg(target(true))] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-target-compact-errors.rs:32:1 | LL | #[cfg(target(clippy::os = "linux"))] @@ -90,4 +90,5 @@ LL + #[cfg(predicate)] error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0539`. +Some errors have detailed explanations: E0539, E0565. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/cfg/path-kw-as-cfg-pred.stderr b/tests/ui/cfg/path-kw-as-cfg-pred.stderr index 17289430c22f5..0fd9d1b9b5fc5 100644 --- a/tests/ui/cfg/path-kw-as-cfg-pred.stderr +++ b/tests/ui/cfg/path-kw-as-cfg-pred.stderr @@ -118,7 +118,7 @@ error: `_` cannot be a raw identifier LL | #[cfg_attr(r#_, cfg(r#_))] | ^^^ -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:20:1 | LL | #[cfg(crate)] @@ -133,7 +133,7 @@ LL - #[cfg(crate)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:22:1 | LL | #[cfg(super)] @@ -148,7 +148,7 @@ LL - #[cfg(super)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:24:1 | LL | #[cfg(self)] @@ -163,7 +163,7 @@ LL - #[cfg(self)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:26:1 | LL | #[cfg(Self)] @@ -178,7 +178,7 @@ LL - #[cfg(Self)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:28:1 | LL | #[cfg_attr(crate, path = "foo")] @@ -193,7 +193,7 @@ LL - #[cfg_attr(crate, path = "foo")] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:30:1 | LL | #[cfg_attr(super, path = "foo")] @@ -208,7 +208,7 @@ LL - #[cfg_attr(super, path = "foo")] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:32:1 | LL | #[cfg_attr(self, path = "foo")] @@ -223,7 +223,7 @@ LL - #[cfg_attr(self, path = "foo")] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:34:1 | LL | #[cfg_attr(Self, path = "foo")] @@ -238,7 +238,7 @@ LL - #[cfg_attr(Self, path = "foo")] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:36:18 | LL | #[cfg_attr(true, cfg(crate))] @@ -253,7 +253,7 @@ LL - #[cfg_attr(true, cfg(crate))] LL + #[cfg_attr(true, cfg(predicate))] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:38:18 | LL | #[cfg_attr(true, cfg(super))] @@ -268,7 +268,7 @@ LL - #[cfg_attr(true, cfg(super))] LL + #[cfg_attr(true, cfg(predicate))] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:40:18 | LL | #[cfg_attr(true, cfg(self))] @@ -283,7 +283,7 @@ LL - #[cfg_attr(true, cfg(self))] LL + #[cfg_attr(true, cfg(predicate))] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:42:18 | LL | #[cfg_attr(true, cfg(Self))] @@ -362,7 +362,7 @@ error: expected identifier, found reserved identifier `_` LL | #[cfg_attr(true, cfg(_))] | ^ expected identifier, found reserved identifier -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:90:1 | LL | #[cfg(r#crate)] @@ -377,7 +377,7 @@ LL - #[cfg(r#crate)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:93:1 | LL | #[cfg(r#super)] @@ -392,7 +392,7 @@ LL - #[cfg(r#super)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:96:1 | LL | #[cfg(r#self)] @@ -407,7 +407,7 @@ LL - #[cfg(r#self)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:99:1 | LL | #[cfg(r#Self)] @@ -422,7 +422,7 @@ LL - #[cfg(r#Self)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:102:1 | LL | #[cfg_attr(r#crate, cfg(r#crate))] @@ -437,7 +437,7 @@ LL - #[cfg_attr(r#crate, cfg(r#crate))] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:106:1 | LL | #[cfg_attr(r#super, cfg(r#super))] @@ -452,7 +452,7 @@ LL - #[cfg_attr(r#super, cfg(r#super))] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:110:1 | LL | #[cfg_attr(r#self, cfg(r#self))] @@ -467,7 +467,7 @@ LL - #[cfg_attr(r#self, cfg(r#self))] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:114:1 | LL | #[cfg_attr(r#Self, cfg(r#Self))] @@ -482,7 +482,7 @@ LL - #[cfg_attr(r#Self, cfg(r#Self))] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:9:9 | LL | #[cfg($crate)] @@ -501,7 +501,7 @@ LL - #[cfg($crate)] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:11:9 | LL | #[cfg_attr($crate, path = "foo")] @@ -520,7 +520,7 @@ LL - #[cfg_attr($crate, path = "foo")] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:13:26 | LL | #[cfg_attr(true, cfg($crate))] @@ -539,7 +539,7 @@ LL - #[cfg_attr(true, cfg($crate))] LL + #[cfg_attr(true, cfg(predicate))] | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:16:9 | LL | cfg!($crate); @@ -558,7 +558,7 @@ LL - cfg!($crate); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:67:5 | LL | cfg!(crate); @@ -573,7 +573,7 @@ LL - cfg!(crate); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:68:5 | LL | cfg!(super); @@ -588,7 +588,7 @@ LL - cfg!(super); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:69:5 | LL | cfg!(self); @@ -603,7 +603,7 @@ LL - cfg!(self); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:70:5 | LL | cfg!(Self); @@ -618,7 +618,7 @@ LL - cfg!(Self); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:72:5 | LL | cfg!(r#crate); @@ -633,7 +633,7 @@ LL - cfg!(r#crate); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:74:5 | LL | cfg!(r#super); @@ -648,7 +648,7 @@ LL - cfg!(r#super); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:76:5 | LL | cfg!(r#self); @@ -663,7 +663,7 @@ LL - cfg!(r#self); LL + cfg!(predicate); | -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/path-kw-as-cfg-pred.rs:78:5 | LL | cfg!(r#Self); @@ -698,4 +698,4 @@ LL | cfg!(_); error: aborting due to 64 previous errors -For more information about this error, try `rustc --explain E0539`. +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 7851758b08069..8098e09fba567 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -59,7 +59,7 @@ LL - #[cfg(a, b)] LL + #[cfg(any(a, b))] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-attr-syntax-validation.rs:25:1 | LL | #[cfg("str")] @@ -74,7 +74,7 @@ LL - #[cfg("str")] LL + #[cfg(predicate)] | -error[E0539]: malformed `cfg` attribute input +error[E0565]: malformed `cfg` attribute input --> $DIR/cfg-attr-syntax-validation.rs:31:1 | LL | #[cfg(a::b)] @@ -133,5 +133,5 @@ LL | generate_s10!(concat!("nonexistent")); error: aborting due to 10 previous errors -Some errors have detailed explanations: E0537, E0539, E0805. +Some errors have detailed explanations: E0537, E0539, E0565, E0805. For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr index 44d4df555c872..0e4b6e8f9dc71 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr @@ -37,7 +37,7 @@ help: must be of the form LL | #[cfg_attr(predicate, attr1, attr2, ...)] | ++++++++++++++++++++++++++++ -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/cfg_attr-attr-syntax-validation.rs:13:1 | LL | #[cfg_attr("str")] @@ -52,7 +52,7 @@ LL - #[cfg_attr("str")] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | -error[E0539]: malformed `cfg_attr` attribute input +error[E0565]: malformed `cfg_attr` attribute input --> $DIR/cfg_attr-attr-syntax-validation.rs:16:1 | LL | #[cfg_attr(a::b)] @@ -177,5 +177,5 @@ LL | #[cfg_attr(true, link_section)] error: aborting due to 13 previous errors; 1 warning emitted -Some errors have detailed explanations: E0537, E0539, E0805. +Some errors have detailed explanations: E0537, E0539, E0565, E0805. For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr index fdc644ed6469c..2605305bfd923 100644 --- a/tests/ui/link-native-libs/issue-43925.stderr +++ b/tests/ui/link-native-libs/issue-43925.stderr @@ -7,7 +7,7 @@ LL | #[link(name = "foo", cfg("rlib"))] = help: add `#![feature(link_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0539]: malformed `link` attribute input +error[E0565]: malformed `link` attribute input --> $DIR/issue-43925.rs:1:1 | LL | #[link(name = "foo", cfg("rlib"))] @@ -19,5 +19,5 @@ LL | #[link(name = "foo", cfg("rlib"))] error: aborting due to 2 previous errors -Some errors have detailed explanations: E0539, E0658. -For more information about an error, try `rustc --explain E0539`. +Some errors have detailed explanations: E0565, E0658. +For more information about an error, try `rustc --explain E0565`. diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index 4a4a193752070..50bed93cef439 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr @@ -148,7 +148,7 @@ LL | #[link(name = "...", cfg = "literal")] | = note: for more information, visit -error[E0539]: malformed `link` attribute input +error[E0565]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:25:1 | LL | #[link(name = "...", cfg("literal"))] diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index d5dee81d33e56..a5ee463f2a346 100644 --- a/tests/ui/macros/cfg.stderr +++ b/tests/ui/macros/cfg.stderr @@ -4,7 +4,7 @@ error: macro requires a cfg-pattern as an argument LL | cfg!(); | ^^^^^^ cfg-pattern required -error[E0539]: malformed `cfg` macro input +error[E0565]: malformed `cfg` macro input --> $DIR/cfg.rs:3:5 | LL | cfg!(123); @@ -53,4 +53,5 @@ LL | cfg!(foo); error: aborting due to 4 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0539`. +Some errors have detailed explanations: E0539, E0565. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 9fd92ad668c2b..99db268bd28b7 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -178,12 +178,12 @@ cfg_select! { cfg_select! { "str" => {} - //~^ ERROR malformed `cfg_select` macro input [E0539] + //~^ ERROR malformed `cfg_select` macro input [E0565] } cfg_select! { a::b => {} - //~^ ERROR malformed `cfg_select` macro input [E0539] + //~^ ERROR malformed `cfg_select` macro input [E0565] } cfg_select! { diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index b8fbe103d2cf1..e5871619b957a 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -25,13 +25,13 @@ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expres LL | () => {} | ^^ expressions are not allowed here -error[E0539]: malformed `cfg_select` macro input +error[E0565]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:180:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here -error[E0539]: malformed `cfg_select` macro input +error[E0565]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:185:5 | LL | a::b => {} @@ -185,5 +185,5 @@ LL | cfg!() => {} error: aborting due to 17 previous errors; 7 warnings emitted -Some errors have detailed explanations: E0537, E0539, E0753. +Some errors have detailed explanations: E0537, E0565, E0753. For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr index 24962cf270a4e..cf80df7c382e5 100644 --- a/tests/ui/proc-macro/attribute.stderr +++ b/tests/ui/proc-macro/attribute.stderr @@ -102,7 +102,7 @@ LL - #[proc_macro_derive(d6 = "")] LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | -error[E0539]: malformed `proc_macro_derive` attribute input +error[E0565]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:45:1 | LL | #[proc_macro_derive(m::d7)] @@ -138,7 +138,7 @@ LL - #[proc_macro_derive(d8(a))] LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | -error[E0539]: malformed `proc_macro_derive` attribute input +error[E0565]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:57:1 | LL | #[proc_macro_derive(self)] @@ -192,7 +192,7 @@ LL - #[proc_macro_derive(d12, attributes)] LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | -error[E0539]: malformed `proc_macro_derive` attribute input +error[E0565]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:78:1 | LL | #[proc_macro_derive(d13, attributes("a"))] @@ -228,7 +228,7 @@ LL - #[proc_macro_derive(d14, attributes(a = ""))] LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | -error[E0539]: malformed `proc_macro_derive` attribute input +error[E0565]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:90:1 | LL | #[proc_macro_derive(d15, attributes(m::a))] @@ -264,7 +264,7 @@ LL - #[proc_macro_derive(d16, attributes(a(b)))] LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | -error[E0539]: malformed `proc_macro_derive` attribute input +error[E0565]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:102:1 | LL | #[proc_macro_derive(d17, attributes(self))] diff --git a/tests/ui/tool-attributes/invalid-tool.stderr b/tests/ui/tool-attributes/invalid-tool.stderr index 0e06af5a6ae17..499894a9200c3 100644 --- a/tests/ui/tool-attributes/invalid-tool.stderr +++ b/tests/ui/tool-attributes/invalid-tool.stderr @@ -1,4 +1,4 @@ -error[E0539]: malformed `register_tool` attribute input +error[E0565]: malformed `register_tool` attribute input --> $DIR/invalid-tool.rs:3:1 | LL | #![register_tool(1)] @@ -14,4 +14,4 @@ LL + #![register_tool(tool1, tool2, ...)] error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0539`. +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/tool-attributes/nested-disallowed.stderr b/tests/ui/tool-attributes/nested-disallowed.stderr index 5e0369711a39f..3cc9c6868998a 100644 --- a/tests/ui/tool-attributes/nested-disallowed.stderr +++ b/tests/ui/tool-attributes/nested-disallowed.stderr @@ -1,4 +1,4 @@ -error[E0539]: malformed `register_tool` attribute input +error[E0565]: malformed `register_tool` attribute input --> $DIR/nested-disallowed.rs:2:1 | LL | #![register_tool(foo::bar)] @@ -14,4 +14,4 @@ LL + #![register_tool(tool1, tool2, ...)] error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0539`. +For more information about this error, try `rustc --explain E0565`. From 872a13faa58e663301bdb6c1a0518a79997164b9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 29 May 2026 23:51:40 +0200 Subject: [PATCH 06/15] Fix foreign items in rustdoc macro expansion feature --- src/librustdoc/html/macro_expansion.rs | 12 +++++++++++- .../macro-expansion/c-var-args.rs | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/macro-expansion/c-var-args.rs diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs index ec8b65984852c..4c820415e273c 100644 --- a/src/librustdoc/html/macro_expansion.rs +++ b/src/librustdoc/html/macro_expansion.rs @@ -2,7 +2,7 @@ use rustc_ast::visit::{ AssocCtxt, Visitor, walk_assoc_item, walk_crate, walk_expr, walk_item, walk_pat, walk_stmt, walk_ty, }; -use rustc_ast::{AssocItem, Crate, Expr, Item, Pat, Stmt, Ty}; +use rustc_ast::{AssocItem, Crate, Expr, ForeignItem, Item, Pat, Stmt, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Span}; @@ -174,4 +174,14 @@ impl<'ast> Visitor<'ast> for ExpandedCodeVisitor<'ast> { walk_assoc_item(self, item, ctxt); } } + + fn visit_foreign_item(&mut self, item: &'ast ForeignItem) -> Self::Result { + if item.span.from_expansion() { + self.handle_new_span(item.span, || { + rustc_ast_pretty::pprust::foreign_item_to_string(item) + }); + } else { + walk_item(self, item); + } + } } diff --git a/tests/rustdoc-html/macro-expansion/c-var-args.rs b/tests/rustdoc-html/macro-expansion/c-var-args.rs new file mode 100644 index 0000000000000..1d42036cc7bf7 --- /dev/null +++ b/tests/rustdoc-html/macro-expansion/c-var-args.rs @@ -0,0 +1,19 @@ +// Ensure that C var args (`va_list`) work. +// Regression test for . + +//@ compile-flags: -Zunstable-options --generate-macro-expansion + +#![crate_name = "foo"] + +//@ has 'src/foo/c-var-args.rs.html' + +macro_rules! print { + () => { + fn printf(...); + }; +} + +//@ has - '//*[@class="expansion"]/*[@class="expanded"]' 'fn printf(...);' +extern "C" { + print! {} +} From c72dc2be5b3e76ad3959d1e980b0840fd4ede0b9 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 29 May 2026 21:22:18 +0200 Subject: [PATCH 07/15] Clean up `extend` function of `ReprParser` --- .../rustc_attr_parsing/src/attributes/repr.rs | 33 ++++++++----------- .../src/session_diagnostics.rs | 7 ---- tests/ui/error-codes/E0565.stderr | 8 +++-- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 0ba32c6ca8fa9..4a896340111ee 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -7,12 +7,13 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; /// Parse #[repr(...)] forms. /// -/// Valid repr contents: any of the primitive integral type names (see -/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use -/// the same discriminant size that the corresponding C enum would or C -/// structure layout, `packed` to remove padding, and `transparent` to delegate representation -/// concerns to the only non-ZST field. -// FIXME(jdonszelmann): is a vec the right representation here even? isn't it just a struct? +/// Valid repr contents: +/// * any of the primitive integral type names to specify enum discriminant type +/// * `Rust`, to use the default `Rust` layout of the type +/// * `C`, to use the same layout for the type that C would use +/// * `align(...)`, to change the alignment requirements of the type +/// * `packed`, to remove padding +/// * `transparent`, to delegate representation concerns to the only non-ZST field. pub(crate) struct ReprParser; impl CombineAttributeParser for ReprParser { @@ -20,7 +21,6 @@ impl CombineAttributeParser for ReprParser { const PATH: &[Symbol] = &[sym::repr]; const CONVERT: ConvertFn = |items, first_span| AttributeKind::Repr { reprs: items, first_span }; - // FIXME(jdonszelmann): never used const TEMPLATE: AttributeTemplate = template!( List: &["C", "Rust", "transparent", "align(...)", "packed(...)", ""], "https://doc.rust-lang.org/reference/type-layout.html#representations" @@ -30,29 +30,24 @@ impl CombineAttributeParser for ReprParser { cx: &mut AcceptContext<'_, '_>, args: &ArgParser, ) -> impl IntoIterator { - let mut reprs = Vec::new(); - let Some(list) = cx.expect_list(args, cx.attr_span) else { - return reprs; + return vec![]; }; if list.is_empty() { let attr_span = cx.attr_span; cx.adcx().warn_empty_attribute(attr_span); - return reprs; + return vec![]; } + let mut reprs = Vec::new(); for param in list.mixed() { - if let Some(_) = param.as_lit() { - cx.emit_err(session_diagnostics::ReprIdent { span: cx.attr_span }); + let Some(item) = param.meta_item() else { + cx.adcx().expected_identifier(param.span()); continue; - } - - reprs.extend( - param.meta_item().and_then(|mi| parse_repr(cx, &mi)).map(|r| (r, param.span())), - ); + }; + reprs.extend(parse_repr(cx, &item).map(|r| (r, param.span()))); } - reprs } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 79235e4fba6ad..e3fc42385e1bb 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -484,13 +484,6 @@ pub(crate) struct InvalidAlignmentValue { pub error_part: String, } -#[derive(Diagnostic)] -#[diag("meta item in `repr` must be an identifier", code = E0565)] -pub(crate) struct ReprIdent { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("unrecognized representation hint", code = E0552)] #[help( diff --git a/tests/ui/error-codes/E0565.stderr b/tests/ui/error-codes/E0565.stderr index 6e56600133d73..7d22501d74a36 100644 --- a/tests/ui/error-codes/E0565.stderr +++ b/tests/ui/error-codes/E0565.stderr @@ -1,8 +1,12 @@ -error[E0565]: meta item in `repr` must be an identifier +error[E0565]: malformed `repr` attribute input --> $DIR/E0565.rs:2:1 | LL | #[repr("C")] - | ^^^^^^^^^^^^ + | ^^^^^^^---^^ + | | + | expected a valid identifier here + | + = note: for more information, visit error: aborting due to 1 previous error From e6b237a6ca1ac8e8e7b510394e01a1136a30def3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 29 May 2026 22:10:53 +0200 Subject: [PATCH 08/15] Clean up `parse_repr` function of `ReprParser` --- .../src/attributes/prelude.rs | 2 +- .../rustc_attr_parsing/src/attributes/repr.rs | 172 ++++++------------ .../src/session_diagnostics.rs | 95 ---------- .../attribute-on-wrong-item-inline-repr.rs | 4 +- ...attribute-on-wrong-item-inline-repr.stderr | 25 +-- tests/ui/attributes/invalid-reprs.rs | 2 +- tests/ui/attributes/invalid-reprs.stderr | 13 +- .../repr-align-in-trait-issue-132391.rs | 2 +- .../repr-align-in-trait-issue-132391.stderr | 12 +- tests/ui/repr/invalid_repr_list_help.rs | 10 +- tests/ui/repr/invalid_repr_list_help.stderr | 57 +++--- tests/ui/repr/malformed-repr-hints.rs | 14 +- tests/ui/repr/malformed-repr-hints.stderr | 74 +++++--- tests/ui/repr/repr-align-assign.fixed | 11 -- tests/ui/repr/repr-align-assign.rs | 6 +- tests/ui/repr/repr-align-assign.stderr | 22 ++- 16 files changed, 204 insertions(+), 317 deletions(-) delete mode 100644 tests/ui/repr/repr-align-assign.fixed diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs index 9b27dd3d53586..ae0c1673ed3b4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs @@ -6,7 +6,7 @@ pub(super) use rustc_hir::attrs::AttributeKind; #[doc(hidden)] pub(super) use rustc_hir::{MethodKind, Target}; #[doc(hidden)] -pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; +pub(super) use rustc_span::{Ident, Span, Symbol, sym}; #[doc(hidden)] pub(super) use thin_vec::ThinVec; diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 4a896340111ee..2d472c3468c62 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -1,9 +1,10 @@ use rustc_abi::{Align, Size}; use rustc_ast::{IntTy, LitIntType, LitKind, UintTy}; -use rustc_hir::attrs::{IntType, ReprAttr}; +use rustc_hir::attrs::IntType::{SignedInt, UnsignedInt}; +use rustc_hir::attrs::ReprAttr; use super::prelude::*; -use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; +use crate::session_diagnostics; /// Parse #[repr(...)] forms. /// @@ -56,122 +57,69 @@ impl CombineAttributeParser for ReprParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); } -macro_rules! int_pat { - () => { - sym::i8 - | sym::u8 - | sym::i16 - | sym::u16 - | sym::i32 - | sym::u32 - | sym::i64 - | sym::u64 - | sym::i128 - | sym::u128 - | sym::isize - | sym::usize - }; -} - -fn int_type_of_word(s: Symbol) -> Option { - use IntType::*; - - match s { - sym::i8 => Some(SignedInt(IntTy::I8)), - sym::u8 => Some(UnsignedInt(UintTy::U8)), - sym::i16 => Some(SignedInt(IntTy::I16)), - sym::u16 => Some(UnsignedInt(UintTy::U16)), - sym::i32 => Some(SignedInt(IntTy::I32)), - sym::u32 => Some(UnsignedInt(UintTy::U32)), - sym::i64 => Some(SignedInt(IntTy::I64)), - sym::u64 => Some(UnsignedInt(UintTy::U64)), - sym::i128 => Some(SignedInt(IntTy::I128)), - sym::u128 => Some(UnsignedInt(UintTy::U128)), - sym::isize => Some(SignedInt(IntTy::Isize)), - sym::usize => Some(UnsignedInt(UintTy::Usize)), - _ => None, - } -} - -fn parse_repr(cx: &AcceptContext<'_, '_>, param: &MetaItemParser) -> Option { +fn parse_repr(cx: &mut AcceptContext<'_, '_>, param: &MetaItemParser) -> Option { use ReprAttr::*; - // FIXME(jdonszelmann): invert the parsing here to match on the word first and then the - // structure. - let (name, ident_span) = if let Some(ident) = param.path().word() { - (Some(ident.name), ident.span) - } else { - (None, DUMMY_SP) - }; - - let args = param.args(); + macro_rules! no_args { + ($constructor: expr) => {{ + cx.expect_no_args(param.args())?; + Some($constructor) + }}; + } - match (name, args) { - (Some(sym::align), ArgParser::NoArgs) => { - cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span }); - None - } - (Some(sym::align), ArgParser::List(l)) => { + match param.path().word_sym() { + Some(sym::align) => { + let l = cx.expect_list(param.args(), param.span())?; parse_repr_align(cx, l, param.span(), AlignKind::Align) } - - (Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)), - (Some(sym::packed), ArgParser::List(l)) => { - parse_repr_align(cx, l, param.span(), AlignKind::Packed) - } - - (Some(name @ sym::align | name @ sym::packed), ArgParser::NameValue(l)) => { - cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric { - span: param.span(), - // FIXME(jdonszelmann) can just be a string in the diag type - repr_arg: name, - cause: IncorrectReprFormatGenericCause::from_lit_kind( - param.span(), - &l.value_as_lit().kind, - name, - ), - }); - None - } - - (Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust), - (Some(sym::C), ArgParser::NoArgs) => Some(ReprC), - (Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd), - (Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent), - (Some(name @ int_pat!()), ArgParser::NoArgs) => { - // int_pat!() should make sure it always parses - Some(ReprInt(int_type_of_word(name).unwrap())) - } - - ( - Some( - name @ sym::Rust - | name @ sym::C - | name @ sym::simd - | name @ sym::transparent - | name @ int_pat!(), - ), - ArgParser::NameValue(_), - ) => { - cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), name }); - None - } - ( - Some( - name @ sym::Rust - | name @ sym::C - | name @ sym::simd - | name @ sym::transparent - | name @ int_pat!(), - ), - ArgParser::List(_), - ) => { - cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), name }); - None - } - + Some(sym::packed) => match param.args() { + ArgParser::NoArgs => Some(ReprPacked(Align::ONE)), + ArgParser::List(l) => parse_repr_align(cx, l, param.span(), AlignKind::Packed), + ArgParser::NameValue(_) => { + cx.adcx().expected_list_or_no_args(param.span()); + None + } + }, + Some(sym::Rust) => no_args!(ReprRust), + Some(sym::C) => no_args!(ReprC), + Some(sym::simd) => no_args!(ReprSimd), + Some(sym::transparent) => no_args!(ReprTransparent), + Some(sym::i8) => no_args!(ReprInt(SignedInt(IntTy::I8))), + Some(sym::u8) => no_args!(ReprInt(UnsignedInt(UintTy::U8))), + Some(sym::i16) => no_args!(ReprInt(SignedInt(IntTy::I16))), + Some(sym::u16) => no_args!(ReprInt(UnsignedInt(UintTy::U16))), + Some(sym::i32) => no_args!(ReprInt(SignedInt(IntTy::I32))), + Some(sym::u32) => no_args!(ReprInt(UnsignedInt(UintTy::U32))), + Some(sym::i64) => no_args!(ReprInt(SignedInt(IntTy::I64))), + Some(sym::u64) => no_args!(ReprInt(UnsignedInt(UintTy::U64))), + Some(sym::i128) => no_args!(ReprInt(SignedInt(IntTy::I128))), + Some(sym::u128) => no_args!(ReprInt(UnsignedInt(UintTy::U128))), + Some(sym::isize) => no_args!(ReprInt(SignedInt(IntTy::Isize))), + Some(sym::usize) => no_args!(ReprInt(UnsignedInt(UintTy::Usize))), _ => { - cx.emit_err(session_diagnostics::UnrecognizedReprHint { span: param.span() }); + cx.adcx().expected_specific_argument( + param.span(), + &[ + sym::align, + sym::packed, + sym::Rust, + sym::C, + sym::simd, + sym::transparent, + sym::i8, + sym::u8, + sym::i16, + sym::u16, + sym::i32, + sym::u32, + sym::i64, + sym::u64, + sym::i128, + sym::u128, + sym::isize, + sym::usize, + ], + ); None } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index e3fc42385e1bb..9ace198499035 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1,6 +1,5 @@ use std::num::IntErrorKind; -use rustc_ast as ast; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, @@ -198,36 +197,6 @@ pub(crate) struct IncorrectReprFormatPackedExpectInteger { pub span: Span, } -#[derive(Diagnostic)] -#[diag("invalid representation hint: `{$name}` does not take a parenthesized argument list", code = E0552)] -pub(crate) struct InvalidReprHintNoParen { - #[primary_span] - pub span: Span, - - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag("invalid representation hint: `{$name}` does not take a value", code = E0552)] -pub(crate) struct InvalidReprHintNoValue { - #[primary_span] - pub span: Span, - - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag("invalid `repr(align)` attribute: `align` needs an argument", code = E0589)] -pub(crate) struct InvalidReprAlignNeedArg { - #[primary_span] - #[suggestion( - "supply an argument here", - code = "align(...)", - applicability = "has-placeholders" - )] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)] pub(crate) struct InvalidReprGeneric { @@ -252,57 +221,6 @@ pub(crate) struct IncorrectReprFormatExpectInteger { pub span: Span, } -#[derive(Diagnostic)] -#[diag("incorrect `repr({$repr_arg})` attribute format", code = E0693)] -pub(crate) struct IncorrectReprFormatGeneric { - #[primary_span] - pub span: Span, - - pub repr_arg: Symbol, - - #[subdiagnostic] - pub cause: Option, -} - -#[derive(Subdiagnostic)] -pub(crate) enum IncorrectReprFormatGenericCause { - #[suggestion( - "use parentheses instead", - code = "{name}({value})", - applicability = "machine-applicable" - )] - Int { - #[primary_span] - span: Span, - name: Symbol, - value: u128, - }, - - #[suggestion( - "use parentheses instead", - code = "{name}({value})", - applicability = "machine-applicable" - )] - Symbol { - #[primary_span] - span: Span, - name: Symbol, - value: Symbol, - }, -} - -impl IncorrectReprFormatGenericCause { - pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: Symbol) -> Option { - match *kind { - ast::LitKind::Int(value, ast::LitIntType::Unsuffixed) => { - Some(Self::Int { span, name, value: value.get() }) - } - ast::LitKind::Str(value, _) => Some(Self::Symbol { span, name, value }), - _ => None, - } - } -} - #[derive(Diagnostic)] #[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)] pub(crate) struct RustcPromotablePairing { @@ -484,19 +402,6 @@ pub(crate) struct InvalidAlignmentValue { pub error_part: String, } -#[derive(Diagnostic)] -#[diag("unrecognized representation hint", code = E0552)] -#[help( - "valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`" -)] -#[note( - "for more information, visit " -)] -pub(crate) struct UnrecognizedReprHint { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("item annotated with `#[unstable_feature_bound]` should not be stable")] #[help( diff --git a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs index c29edbe14f244..be9fd7d352179 100644 --- a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs +++ b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.rs @@ -16,13 +16,13 @@ fn main() { #[repr(nothing)] let _x = 0; - //~^^ ERROR E0552 + //~^^ ERROR malformed `repr` attribute input #[repr(something_not_real)] loop { () }; - //~^^^^ ERROR E0552 + //~^^^^ ERROR malformed `repr` attribute input #[repr] let _y = "123"; diff --git a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr index 49f67bf6ad044..f9f17b1db10d7 100644 --- a/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr +++ b/tests/ui/attributes/attribute-on-wrong-item-inline-repr.stderr @@ -35,23 +35,25 @@ LL | #[inline(XYZ)] | = help: `#[inline]` can only be applied to functions -error[E0552]: unrecognized representation hint - --> $DIR/attribute-on-wrong-item-inline-repr.rs:17:12 +error[E0539]: malformed `repr` attribute input + --> $DIR/attribute-on-wrong-item-inline-repr.rs:17:5 | LL | #[repr(nothing)] - | ^^^^^^^ + | ^^^^^^^-------^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit -error[E0552]: unrecognized representation hint - --> $DIR/attribute-on-wrong-item-inline-repr.rs:21:12 +error[E0539]: malformed `repr` attribute input + --> $DIR/attribute-on-wrong-item-inline-repr.rs:21:5 | LL | #[repr(something_not_real)] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^------------------^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit error[E0539]: malformed `repr` attribute input --> $DIR/attribute-on-wrong-item-inline-repr.rs:27:5 @@ -100,5 +102,4 @@ LL | let _z = #[repr] 1; error: aborting due to 9 previous errors -Some errors have detailed explanations: E0539, E0552. -For more information about an error, try `rustc --explain E0539`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/invalid-reprs.rs b/tests/ui/attributes/invalid-reprs.rs index 95ed14b549163..f15d721495e0e 100644 --- a/tests/ui/attributes/invalid-reprs.rs +++ b/tests/ui/attributes/invalid-reprs.rs @@ -1,6 +1,6 @@ fn main() { let y = #[repr(uwu(4))] //~^ ERROR attributes on expressions are experimental - //~| ERROR unrecognized representation hint + //~| ERROR malformed `repr` attribute input (&id(5)); //~ ERROR: cannot find function `id` in this scope } diff --git a/tests/ui/attributes/invalid-reprs.stderr b/tests/ui/attributes/invalid-reprs.stderr index 72aaff92bd007..3cc52f552e1cc 100644 --- a/tests/ui/attributes/invalid-reprs.stderr +++ b/tests/ui/attributes/invalid-reprs.stderr @@ -19,16 +19,17 @@ help: consider importing this function LL + use std::process::id; | -error[E0552]: unrecognized representation hint - --> $DIR/invalid-reprs.rs:2:20 +error[E0539]: malformed `repr` attribute input + --> $DIR/invalid-reprs.rs:2:13 | LL | let y = #[repr(uwu(4))] - | ^^^^^^ + | ^^^^^^^------^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit error: aborting due to 3 previous errors -Some errors have detailed explanations: E0425, E0552, E0658. +Some errors have detailed explanations: E0425, E0539, E0658. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/attributes/repr-align-in-trait-issue-132391.rs b/tests/ui/attributes/repr-align-in-trait-issue-132391.rs index b3b79e93e9bd8..7b9f6c12deadb 100644 --- a/tests/ui/attributes/repr-align-in-trait-issue-132391.rs +++ b/tests/ui/attributes/repr-align-in-trait-issue-132391.rs @@ -1,5 +1,5 @@ trait MyTrait { - #[repr(align)] //~ ERROR invalid `repr(align)` attribute: `align` needs an argument + #[repr(align)] //~ ERROR malformed `repr` attribute input fn myfun(); } diff --git a/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr b/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr index 4208b018f52f0..a8f5d3bab584a 100644 --- a/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr +++ b/tests/ui/attributes/repr-align-in-trait-issue-132391.stderr @@ -1,9 +1,13 @@ -error[E0589]: invalid `repr(align)` attribute: `align` needs an argument - --> $DIR/repr-align-in-trait-issue-132391.rs:2:12 +error[E0539]: malformed `repr` attribute input + --> $DIR/repr-align-in-trait-issue-132391.rs:2:5 | LL | #[repr(align)] - | ^^^^^ help: supply an argument here: `align(...)` + | ^^^^^^^-----^^ + | | + | expected this to be a list + | + = note: for more information, visit error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0589`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/repr/invalid_repr_list_help.rs b/tests/ui/repr/invalid_repr_list_help.rs index e8bf5fdcd3fd4..407514d014d8a 100644 --- a/tests/ui/repr/invalid_repr_list_help.rs +++ b/tests/ui/repr/invalid_repr_list_help.rs @@ -1,22 +1,22 @@ #![deny(invalid_doc_attributes)] #![crate_type = "lib"] -#[repr(uwu)] //~ERROR: unrecognized representation hint +#[repr(uwu)] //~ERROR: malformed `repr` attribute input pub struct OwO; -#[repr(uwu = "a")] //~ERROR: unrecognized representation hint +#[repr(uwu = "a")] //~ERROR: malformed `repr` attribute input pub struct OwO2(i32); -#[repr(uwu(4))] //~ERROR: unrecognized representation hint +#[repr(uwu(4))] //~ERROR: malformed `repr` attribute input pub struct OwO3 { x: i32, } -#[repr(uwu, u8)] //~ERROR: unrecognized representation hint +#[repr(uwu, u8)] //~ERROR: malformed `repr` attribute input pub enum OwO4 { UwU = 1, } -#[repr(uwu)] //~ERROR: unrecognized representation hint +#[repr(uwu)] //~ERROR: malformed `repr` attribute input #[doc(owo)] //~ERROR: unknown `doc` attribute pub struct Owo5; diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index 3226508148283..82bf12f3f4dbc 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -1,47 +1,52 @@ -error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:4:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/invalid_repr_list_help.rs:4:1 | LL | #[repr(uwu)] - | ^^^ + | ^^^^^^^---^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit -error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:7:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/invalid_repr_list_help.rs:7:1 | LL | #[repr(uwu = "a")] - | ^^^^^^^^^ + | ^^^^^^^---------^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit -error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:10:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/invalid_repr_list_help.rs:10:1 | LL | #[repr(uwu(4))] - | ^^^^^^ + | ^^^^^^^------^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit -error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:15:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/invalid_repr_list_help.rs:15:1 | LL | #[repr(uwu, u8)] - | ^^^ + | ^^^^^^^---^^^^^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit -error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:20:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/invalid_repr_list_help.rs:20:1 | LL | #[repr(uwu)] - | ^^^ + | ^^^^^^^---^^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | - = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - = note: for more information, visit + = note: for more information, visit error: unknown `doc` attribute `owo` --> $DIR/invalid_repr_list_help.rs:21:7 @@ -57,4 +62,4 @@ LL | #![deny(invalid_doc_attributes)] error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0552`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/repr/malformed-repr-hints.rs b/tests/ui/repr/malformed-repr-hints.rs index 09c808a041df3..7a010d7bdfcd8 100644 --- a/tests/ui/repr/malformed-repr-hints.rs +++ b/tests/ui/repr/malformed-repr-hints.rs @@ -8,7 +8,7 @@ struct S1; #[repr(align)] -//~^ ERROR: invalid `repr(align)` attribute +//~^ ERROR: malformed `repr` attribute input struct S2; #[repr(align(2, 4))] @@ -21,23 +21,23 @@ struct S4; // Regression test for issue #118334: #[repr(Rust(u8))] -//~^ ERROR: invalid representation hint +//~^ ERROR: malformed `repr` attribute input #[repr(Rust(0))] -//~^ ERROR: invalid representation hint +//~^ ERROR: malformed `repr` attribute input #[repr(Rust = 0)] -//~^ ERROR: invalid representation hint +//~^ ERROR: malformed `repr` attribute input struct S5; #[repr(i8())] -//~^ ERROR: invalid representation hint +//~^ ERROR: malformed `repr` attribute input enum E1 { A, B } #[repr(u32(42))] -//~^ ERROR: invalid representation hint +//~^ ERROR: malformed `repr` attribute input enum E2 { A, B } #[repr(i64 = 2)] -//~^ ERROR: invalid representation hint +//~^ ERROR: malformed `repr` attribute input enum E3 { A, B } fn main() {} diff --git a/tests/ui/repr/malformed-repr-hints.stderr b/tests/ui/repr/malformed-repr-hints.stderr index 6fb927557619f..3609b7f86ebd4 100644 --- a/tests/ui/repr/malformed-repr-hints.stderr +++ b/tests/ui/repr/malformed-repr-hints.stderr @@ -4,11 +4,15 @@ error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly LL | #[repr(packed())] | ^^^^^^^^ -error[E0589]: invalid `repr(align)` attribute: `align` needs an argument - --> $DIR/malformed-repr-hints.rs:10:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:10:1 | LL | #[repr(align)] - | ^^^^^ help: supply an argument here: `align(...)` + | ^^^^^^^-----^^ + | | + | expected this to be a list + | + = note: for more information, visit error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses --> $DIR/malformed-repr-hints.rs:14:8 @@ -22,43 +26,67 @@ error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly on LL | #[repr(align())] | ^^^^^^^ -error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list - --> $DIR/malformed-repr-hints.rs:23:8 +error[E0565]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:23:1 | LL | #[repr(Rust(u8))] - | ^^^^^^^^ + | ^^^^^^^^^^^----^^ + | | + | didn't expect any arguments here + | + = note: for more information, visit -error[E0552]: invalid representation hint: `Rust` does not take a parenthesized argument list - --> $DIR/malformed-repr-hints.rs:25:8 +error[E0565]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:25:1 | LL | #[repr(Rust(0))] - | ^^^^^^^ + | ^^^^^^^^^^^---^^ + | | + | didn't expect any arguments here + | + = note: for more information, visit -error[E0552]: invalid representation hint: `Rust` does not take a value - --> $DIR/malformed-repr-hints.rs:27:8 +error[E0565]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:27:1 | LL | #[repr(Rust = 0)] - | ^^^^^^^^ + | ^^^^^^^^^^^^---^^ + | | + | didn't expect any arguments here + | + = note: for more information, visit -error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list - --> $DIR/malformed-repr-hints.rs:31:8 +error[E0565]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:31:1 | LL | #[repr(i8())] - | ^^^^ + | ^^^^^^^^^--^^ + | | + | didn't expect any arguments here + | + = note: for more information, visit -error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list - --> $DIR/malformed-repr-hints.rs:35:8 +error[E0565]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:35:1 | LL | #[repr(u32(42))] - | ^^^^^^^ + | ^^^^^^^^^^----^^ + | | + | didn't expect any arguments here + | + = note: for more information, visit -error[E0552]: invalid representation hint: `i64` does not take a value - --> $DIR/malformed-repr-hints.rs:39:8 +error[E0565]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:39:1 | LL | #[repr(i64 = 2)] - | ^^^^^^^ + | ^^^^^^^^^^^---^^ + | | + | didn't expect any arguments here + | + = note: for more information, visit error: aborting due to 10 previous errors -Some errors have detailed explanations: E0552, E0589, E0693. -For more information about an error, try `rustc --explain E0552`. +Some errors have detailed explanations: E0539, E0552, E0565, E0693. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/repr/repr-align-assign.fixed b/tests/ui/repr/repr-align-assign.fixed deleted file mode 100644 index 96f9866611bc1..0000000000000 --- a/tests/ui/repr/repr-align-assign.fixed +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-rustfix - -#![allow(dead_code)] - -#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format -struct A(u64); - -#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format -struct B(u64); - -fn main() {} diff --git a/tests/ui/repr/repr-align-assign.rs b/tests/ui/repr/repr-align-assign.rs index 0b30ee6566461..a7fe2f2121a12 100644 --- a/tests/ui/repr/repr-align-assign.rs +++ b/tests/ui/repr/repr-align-assign.rs @@ -1,11 +1,9 @@ -//@ run-rustfix - #![allow(dead_code)] -#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format +#[repr(align=8)] //~ ERROR malformed `repr` attribute input struct A(u64); -#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format +#[repr(align="8")] //~ ERROR malformed `repr` attribute input struct B(u64); fn main() {} diff --git a/tests/ui/repr/repr-align-assign.stderr b/tests/ui/repr/repr-align-assign.stderr index cc046e04de542..f81cdf532fdaf 100644 --- a/tests/ui/repr/repr-align-assign.stderr +++ b/tests/ui/repr/repr-align-assign.stderr @@ -1,15 +1,23 @@ -error[E0693]: incorrect `repr(align)` attribute format - --> $DIR/repr-align-assign.rs:5:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/repr-align-assign.rs:3:1 | LL | #[repr(align=8)] - | ^^^^^^^ help: use parentheses instead: `align(8)` + | ^^^^^^^^^^^^--^^ + | | + | expected this to be a list + | + = note: for more information, visit -error[E0693]: incorrect `repr(align)` attribute format - --> $DIR/repr-align-assign.rs:8:8 +error[E0539]: malformed `repr` attribute input + --> $DIR/repr-align-assign.rs:6:1 | LL | #[repr(align="8")] - | ^^^^^^^^^ help: use parentheses instead: `align(8)` + | ^^^^^^^^^^^^----^^ + | | + | expected this to be a list + | + = note: for more information, visit error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0693`. +For more information about this error, try `rustc --explain E0539`. From 7aef596de465f1f3a5432ccbdcf34d52f5f62ef2 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 29 May 2026 22:19:20 +0200 Subject: [PATCH 09/15] Clean up `parse_repr_align` function of `ReprParser` --- .../rustc_attr_parsing/src/attributes/repr.rs | 48 +++---------------- .../src/session_diagnostics.rs | 39 --------------- .../src/error_codes/E0552.md | 5 +- .../src/error_codes/E0693.md | 5 +- tests/ui/attributes/arg-error-issue-121425.rs | 12 ++--- .../attributes/arg-error-issue-121425.stderr | 48 ++++++++++++------- tests/ui/attributes/malformed-reprs.rs | 2 +- tests/ui/attributes/malformed-reprs.stderr | 2 +- tests/ui/repr/malformed-repr-hints.rs | 6 +-- tests/ui/repr/malformed-repr-hints.stderr | 32 +++++++++---- tests/ui/repr/repr-align.rs | 16 +++---- tests/ui/repr/repr-align.stderr | 16 +++---- .../repr_align_greater_usize.msp430.stderr | 4 +- tests/ui/repr/repr_align_greater_usize.rs | 4 +- 14 files changed, 100 insertions(+), 139 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 2d472c3468c62..e3d5ba891a5dd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -70,11 +70,11 @@ fn parse_repr(cx: &mut AcceptContext<'_, '_>, param: &MetaItemParser) -> Option< match param.path().word_sym() { Some(sym::align) => { let l = cx.expect_list(param.args(), param.span())?; - parse_repr_align(cx, l, param.span(), AlignKind::Align) + parse_repr_align(cx, l, AlignKind::Align) } Some(sym::packed) => match param.args() { ArgParser::NoArgs => Some(ReprPacked(Align::ONE)), - ArgParser::List(l) => parse_repr_align(cx, l, param.span(), AlignKind::Packed), + ArgParser::List(l) => parse_repr_align(cx, l, AlignKind::Packed), ArgParser::NameValue(_) => { cx.adcx().expected_list_or_no_args(param.span()); None @@ -131,44 +131,17 @@ enum AlignKind { } fn parse_repr_align( - cx: &AcceptContext<'_, '_>, + cx: &mut AcceptContext<'_, '_>, list: &MetaItemListParser, - param_span: Span, align_kind: AlignKind, ) -> Option { - use AlignKind::*; - let Some(align) = list.as_single() else { - match align_kind { - Packed => { - cx.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg { - span: param_span, - }); - } - Align => { - cx.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { - span: param_span, - }); - } - } - + cx.adcx().expected_single_argument(list.span, list.len()); return None; }; let Some(lit) = align.as_lit() else { - match align_kind { - Packed => { - cx.emit_err(session_diagnostics::IncorrectReprFormatPackedExpectInteger { - span: align.span(), - }); - } - Align => { - cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger { - span: align.span(), - }); - } - } - + cx.adcx().expected_integer_literal(align.span()); return None; }; @@ -178,12 +151,8 @@ fn parse_repr_align( AlignKind::Align => ReprAttr::ReprAlign(literal), }), Err(message) => { - cx.emit_err(session_diagnostics::InvalidReprGeneric { + cx.emit_err(session_diagnostics::InvalidAlignmentValue { span: lit.span, - repr_arg: match align_kind { - Packed => "packed".to_string(), - Align => "align".to_string(), - }, error_part: message, }); None @@ -237,10 +206,7 @@ impl RustcAlignParser { }; let Some(lit) = align.as_lit() else { - cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger { - span: align.span(), - }); - + cx.adcx().expected_integer_literal(align.span()); return; }; diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 9ace198499035..9faf0606495b4 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -182,45 +182,6 @@ pub(crate) struct MissingIssue { pub span: Span, } -// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? -// It is more similar to `IncorrectReprFormatGeneric`. -#[derive(Diagnostic)] -#[diag("incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all", code = E0552)] -pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { - #[primary_span] - pub span: Span, -} -#[derive(Diagnostic)] -#[diag("incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument", code = E0552)] -pub(crate) struct IncorrectReprFormatPackedExpectInteger { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)] -pub(crate) struct InvalidReprGeneric { - #[primary_span] - pub span: Span, - - pub repr_arg: String, - pub error_part: String, -} - -#[derive(Diagnostic)] -#[diag("incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses", code = E0693)] -pub(crate) struct IncorrectReprFormatAlignOneArg { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("incorrect `repr(align)` attribute format: `align` expects a literal integer as argument", code = E0693)] -pub(crate) struct IncorrectReprFormatExpectInteger { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)] pub(crate) struct RustcPromotablePairing { diff --git a/compiler/rustc_error_codes/src/error_codes/E0552.md b/compiler/rustc_error_codes/src/error_codes/E0552.md index 0fbc861fb7ca7..c7bd1806268af 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0552.md +++ b/compiler/rustc_error_codes/src/error_codes/E0552.md @@ -1,8 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. +This error code was replaced by `E0539`. + A unrecognized representation attribute was used. Erroneous code example: -```compile_fail,E0552 +```compile_fail #[repr(D)] // error: unrecognized representation hint struct MyStruct { my_field: usize diff --git a/compiler/rustc_error_codes/src/error_codes/E0693.md b/compiler/rustc_error_codes/src/error_codes/E0693.md index 43e9d17979e68..c9dca8f69bca6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0693.md +++ b/compiler/rustc_error_codes/src/error_codes/E0693.md @@ -1,8 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. +This error code was replaced by `E0539`. + `align` representation hint was incorrectly declared. Erroneous code examples: -```compile_fail,E0693 +```compile_fail #[repr(align=8)] // error! struct Align8(i8); diff --git a/tests/ui/attributes/arg-error-issue-121425.rs b/tests/ui/attributes/arg-error-issue-121425.rs index c15b276ad4eb2..1ff36c619ca07 100644 --- a/tests/ui/attributes/arg-error-issue-121425.rs +++ b/tests/ui/attributes/arg-error-issue-121425.rs @@ -2,28 +2,28 @@ const N: usize = 8; #[repr(align(N))] -//~^ ERROR: incorrect `repr(align)` attribute format +//~^ ERROR: malformed `repr` attribute input struct T; #[repr(align('a'))] -//~^ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer [E0589] +//~^ ERROR: not an unsuffixed integer [E0589] struct H; #[repr(align("str"))] -//~^ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer [E0589] +//~^ ERROR: not an unsuffixed integer [E0589] struct L; #[repr(align())] -//~^ ERROR: attribute format: `align` takes exactly one argument in parentheses +//~^ ERROR: malformed `repr` attribute input struct X; const P: usize = 8; #[repr(packed(P))] -//~^ ERROR: attribute format: `packed` expects a literal integer as argument +//~^ ERROR: malformed `repr` attribute input struct A; #[repr(packed())] -//~^ ERROR: attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all +//~^ ERROR: malformed `repr` attribute input struct B; #[repr(packed)] diff --git a/tests/ui/attributes/arg-error-issue-121425.stderr b/tests/ui/attributes/arg-error-issue-121425.stderr index 1beb99b1703cf..7816ce4a4f377 100644 --- a/tests/ui/attributes/arg-error-issue-121425.stderr +++ b/tests/ui/attributes/arg-error-issue-121425.stderr @@ -1,40 +1,56 @@ -error[E0693]: incorrect `repr(align)` attribute format: `align` expects a literal integer as argument - --> $DIR/arg-error-issue-121425.rs:4:14 +error[E0539]: malformed `repr` attribute input + --> $DIR/arg-error-issue-121425.rs:4:1 | LL | #[repr(align(N))] - | ^ + | ^^^^^^^^^^^^^-^^^ + | | + | expected an integer literal here + | + = note: for more information, visit -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer +error[E0589]: invalid alignment value: not an unsuffixed integer --> $DIR/arg-error-issue-121425.rs:8:14 | LL | #[repr(align('a'))] | ^^^ -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer +error[E0589]: invalid alignment value: not an unsuffixed integer --> $DIR/arg-error-issue-121425.rs:12:14 | LL | #[repr(align("str"))] | ^^^^^ -error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/arg-error-issue-121425.rs:16:8 +error[E0805]: malformed `repr` attribute input + --> $DIR/arg-error-issue-121425.rs:16:1 | LL | #[repr(align())] - | ^^^^^^^ + | ^^^^^^^^^^^^--^^ + | | + | expected an argument here + | + = note: for more information, visit -error[E0552]: incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument - --> $DIR/arg-error-issue-121425.rs:21:15 +error[E0539]: malformed `repr` attribute input + --> $DIR/arg-error-issue-121425.rs:21:1 | LL | #[repr(packed(P))] - | ^ + | ^^^^^^^^^^^^^^-^^^ + | | + | expected an integer literal here + | + = note: for more information, visit -error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all - --> $DIR/arg-error-issue-121425.rs:25:8 +error[E0805]: malformed `repr` attribute input + --> $DIR/arg-error-issue-121425.rs:25:1 | LL | #[repr(packed())] - | ^^^^^^^^ + | ^^^^^^^^^^^^^--^^ + | | + | expected an argument here + | + = note: for more information, visit error: aborting due to 6 previous errors -Some errors have detailed explanations: E0552, E0589, E0693. -For more information about an error, try `rustc --explain E0552`. +Some errors have detailed explanations: E0539, E0589, E0805. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/malformed-reprs.rs b/tests/ui/attributes/malformed-reprs.rs index 4f99239d21b50..9827d10c4ba71 100644 --- a/tests/ui/attributes/malformed-reprs.rs +++ b/tests/ui/attributes/malformed-reprs.rs @@ -7,7 +7,7 @@ // This is a regression test for https://github.com/rust-lang/rust/issues/143479 #[repr(align(0))] -//~^ ERROR invalid `repr(align)` attribute: not a power of two +//~^ ERROR not a power of two //~| ERROR unsupported representation for zero-variant enum [E0084] enum Foo {} diff --git a/tests/ui/attributes/malformed-reprs.stderr b/tests/ui/attributes/malformed-reprs.stderr index 6e77c6e4b9a97..6a5f6492fcab0 100644 --- a/tests/ui/attributes/malformed-reprs.stderr +++ b/tests/ui/attributes/malformed-reprs.stderr @@ -21,7 +21,7 @@ LL - #![repr] LL + #[repr] | -error[E0589]: invalid `repr(align)` attribute: not a power of two +error[E0589]: invalid alignment value: not a power of two --> $DIR/malformed-reprs.rs:9:14 | LL | #[repr(align(0))] diff --git a/tests/ui/repr/malformed-repr-hints.rs b/tests/ui/repr/malformed-repr-hints.rs index 7a010d7bdfcd8..de8ea89a8dd9e 100644 --- a/tests/ui/repr/malformed-repr-hints.rs +++ b/tests/ui/repr/malformed-repr-hints.rs @@ -4,7 +4,7 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes #[repr(packed())] -//~^ ERROR: incorrect `repr(packed)` attribute format +//~^ ERROR: malformed `repr` attribute input struct S1; #[repr(align)] @@ -12,11 +12,11 @@ struct S1; struct S2; #[repr(align(2, 4))] -//~^ ERROR: incorrect `repr(align)` attribute format +//~^ ERROR: malformed `repr` attribute input struct S3; #[repr(align())] -//~^ ERROR: incorrect `repr(align)` attribute format +//~^ ERROR: malformed `repr` attribute input struct S4; // Regression test for issue #118334: diff --git a/tests/ui/repr/malformed-repr-hints.stderr b/tests/ui/repr/malformed-repr-hints.stderr index 3609b7f86ebd4..5911d11fc87af 100644 --- a/tests/ui/repr/malformed-repr-hints.stderr +++ b/tests/ui/repr/malformed-repr-hints.stderr @@ -1,8 +1,12 @@ -error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all - --> $DIR/malformed-repr-hints.rs:6:8 +error[E0805]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:6:1 | LL | #[repr(packed())] - | ^^^^^^^^ + | ^^^^^^^^^^^^^--^^ + | | + | expected an argument here + | + = note: for more information, visit error[E0539]: malformed `repr` attribute input --> $DIR/malformed-repr-hints.rs:10:1 @@ -14,17 +18,25 @@ LL | #[repr(align)] | = note: for more information, visit -error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/malformed-repr-hints.rs:14:8 +error[E0805]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:14:1 | LL | #[repr(align(2, 4))] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^------^^ + | | + | expected a single argument here + | + = note: for more information, visit -error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - --> $DIR/malformed-repr-hints.rs:18:8 +error[E0805]: malformed `repr` attribute input + --> $DIR/malformed-repr-hints.rs:18:1 | LL | #[repr(align())] - | ^^^^^^^ + | ^^^^^^^^^^^^--^^ + | | + | expected an argument here + | + = note: for more information, visit error[E0565]: malformed `repr` attribute input --> $DIR/malformed-repr-hints.rs:23:1 @@ -88,5 +100,5 @@ LL | #[repr(i64 = 2)] error: aborting due to 10 previous errors -Some errors have detailed explanations: E0539, E0552, E0565, E0693. +Some errors have detailed explanations: E0539, E0565, E0805. For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/repr/repr-align.rs b/tests/ui/repr/repr-align.rs index 6b60a765461ab..64c5311640470 100644 --- a/tests/ui/repr/repr-align.rs +++ b/tests/ui/repr/repr-align.rs @@ -1,33 +1,33 @@ #![allow(dead_code)] -#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer +#[repr(align(16.0))] //~ ERROR: not an unsuffixed integer struct S0(i32); -#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two +#[repr(align(15))] //~ ERROR: not a power of two struct S1(i32); -#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 +#[repr(align(4294967296))] //~ ERROR: larger than 2^29 struct S2(i32); #[repr(align(536870912))] // ok: this is the largest accepted alignment struct S3(i32); -#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two +#[repr(align(0))] //~ ERROR: not a power of two struct S4(i32); -#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer +#[repr(align(16.0))] //~ ERROR: not an unsuffixed integer enum E0 { A, B } -#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two +#[repr(align(15))] //~ ERROR: not a power of two enum E1 { A, B } -#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 +#[repr(align(4294967296))] //~ ERROR: larger than 2^29 enum E2 { A, B } #[repr(align(536870912))] // ok: this is the largest accepted alignment enum E3 { A, B } -#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two +#[repr(align(0))] //~ ERROR: not a power of two enum E4 { A, B } fn main() {} diff --git a/tests/ui/repr/repr-align.stderr b/tests/ui/repr/repr-align.stderr index fe919e30b1534..9c0185be7862b 100644 --- a/tests/ui/repr/repr-align.stderr +++ b/tests/ui/repr/repr-align.stderr @@ -1,46 +1,46 @@ -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer +error[E0589]: invalid alignment value: not an unsuffixed integer --> $DIR/repr-align.rs:3:14 | LL | #[repr(align(16.0))] | ^^^^ -error[E0589]: invalid `repr(align)` attribute: not a power of two +error[E0589]: invalid alignment value: not a power of two --> $DIR/repr-align.rs:6:14 | LL | #[repr(align(15))] | ^^ -error[E0589]: invalid `repr(align)` attribute: larger than 2^29 +error[E0589]: invalid alignment value: larger than 2^29 --> $DIR/repr-align.rs:9:14 | LL | #[repr(align(4294967296))] | ^^^^^^^^^^ -error[E0589]: invalid `repr(align)` attribute: not a power of two +error[E0589]: invalid alignment value: not a power of two --> $DIR/repr-align.rs:15:14 | LL | #[repr(align(0))] | ^ -error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer +error[E0589]: invalid alignment value: not an unsuffixed integer --> $DIR/repr-align.rs:18:14 | LL | #[repr(align(16.0))] | ^^^^ -error[E0589]: invalid `repr(align)` attribute: not a power of two +error[E0589]: invalid alignment value: not a power of two --> $DIR/repr-align.rs:21:14 | LL | #[repr(align(15))] | ^^ -error[E0589]: invalid `repr(align)` attribute: larger than 2^29 +error[E0589]: invalid alignment value: larger than 2^29 --> $DIR/repr-align.rs:24:14 | LL | #[repr(align(4294967296))] | ^^^^^^^^^^ -error[E0589]: invalid `repr(align)` attribute: not a power of two +error[E0589]: invalid alignment value: not a power of two --> $DIR/repr-align.rs:30:14 | LL | #[repr(align(0))] diff --git a/tests/ui/repr/repr_align_greater_usize.msp430.stderr b/tests/ui/repr/repr_align_greater_usize.msp430.stderr index 4fcd33d50d749..1045e6e0a5355 100644 --- a/tests/ui/repr/repr_align_greater_usize.msp430.stderr +++ b/tests/ui/repr/repr_align_greater_usize.msp430.stderr @@ -1,10 +1,10 @@ -error[E0589]: invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target) +error[E0589]: invalid alignment value: alignment larger than `isize::MAX` bytes (32767 for the current target) --> $DIR/repr_align_greater_usize.rs:23:14 | LL | #[repr(align(32768))] | ^^^^^ -error[E0589]: invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target) +error[E0589]: invalid alignment value: alignment larger than `isize::MAX` bytes (32767 for the current target) --> $DIR/repr_align_greater_usize.rs:26:14 | LL | #[repr(align(65536))] diff --git a/tests/ui/repr/repr_align_greater_usize.rs b/tests/ui/repr/repr_align_greater_usize.rs index 7df1fbe762661..9f4eb8e272e34 100644 --- a/tests/ui/repr/repr_align_greater_usize.rs +++ b/tests/ui/repr/repr_align_greater_usize.rs @@ -20,8 +20,8 @@ use minicore::*; #[repr(align(16384))] struct Kitten; -#[repr(align(32768))] //[msp430]~ ERROR invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589] +#[repr(align(32768))] //[msp430]~ ERROR alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589] struct Cat; -#[repr(align(65536))] //[msp430]~ ERROR invalid `repr(align)` attribute: alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589] +#[repr(align(65536))] //[msp430]~ ERROR alignment larger than `isize::MAX` bytes (32767 for the current target) [E0589] struct BigCat; From 814e36f7c632ca4fb1d003fe67b059aaac079178 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 30 May 2026 12:10:40 +0200 Subject: [PATCH 10/15] Revert "drop derive helpers during ast lowering" This reverts commit 29e92731 --- compiler/rustc_attr_parsing/src/interface.rs | 23 +++----------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index eb49f108b0414..ffe0451f29aa9 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -285,11 +285,6 @@ impl<'sess> AttributeParser<'sess> { mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute), ) -> Vec { let mut attributes = Vec::new(); - // We store the attributes we intend to discard at the end of this function in order to - // check they are applied to the right target and error out if necessary. In practice, we - // end up dropping only derive attributes and derive helpers, both being fully processed - // at macro expansion. - let mut dropped_attributes = Vec::new(); let mut attr_paths: Vec> = Vec::new(); let mut early_parsed_state = EarlyParsedState::default(); @@ -437,20 +432,8 @@ impl<'sess> AttributeParser<'sess> { self.check_invalid_crate_level_attr_item(&attr, n.item.span()); } - let attr = Attribute::Unparsed(Box::new(attr)); - - if self.tools.is_some_and(|tools| { - tools.iter().any(|tool| tool.name == parts[0]) - // FIXME: this can be removed once #152369 has been merged. - // https://github.com/rust-lang/rust/pull/152369 - || [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn] - .contains(&parts[0]) - }) { - attributes.push(attr); - } else { - dropped_attributes.push(attr); - } - } + attributes.push(Attribute::Unparsed(Box::new(attr))); + }; } } } @@ -466,7 +449,7 @@ impl<'sess> AttributeParser<'sess> { } if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate { - self.check_invalid_where_predicate_attrs(attributes.iter().chain(&dropped_attributes)); + self.check_invalid_where_predicate_attrs(attributes.iter()); } attributes From 5be84518f437d9872cb42322d32a80b39e17a6ec Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 30 May 2026 12:18:29 +0200 Subject: [PATCH 11/15] Add regression test --- tests/rustdoc-json/attrs/derive_helper.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/rustdoc-json/attrs/derive_helper.rs diff --git a/tests/rustdoc-json/attrs/derive_helper.rs b/tests/rustdoc-json/attrs/derive_helper.rs new file mode 100644 index 0000000000000..278d0072decdd --- /dev/null +++ b/tests/rustdoc-json/attrs/derive_helper.rs @@ -0,0 +1,7 @@ +//@ is "$.index[?(@.name=='A')].attrs" '[{"other": "#[default]"}]' +#[derive(Default)] +pub enum Test { + #[default] + A, + B, +} From a0bf3a5b9eac4f76f05e80c66578ac30f6243291 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 30 May 2026 08:05:22 -0400 Subject: [PATCH 12/15] Revert "Add missing --set rust.codegen-backends=["gcc"] in the gcc codegen Dockerfile for the core tests" This reverts commit fd0c5f37e79ace0c3e547b65ec1087dfe12cb10d. The correct fix was made in PR 157007. --- src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile index d0f0b461c0f59..773bd11b9abfb 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-gcc-core-tests/Dockerfile @@ -43,5 +43,4 @@ ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \ --set llvm.libzstd=true" ENV SCRIPT="python3 ../x.py \ --stage 1 \ - test library/coretests \ - --set rust.codegen-backends=[\\\"gcc\\\"]" + test library/coretests" From cef7bd706462d6ae413d1dbf1cfdf99b6d2e2e1a Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Mon, 18 May 2026 12:32:48 +0000 Subject: [PATCH 13/15] Yield drop assigns to the resume_arg. --- compiler/rustc_middle/src/mir/syntax.rs | 19 +++++++---- compiler/rustc_middle/src/mir/terminator.rs | 32 ++++++++----------- .../src/framework/direction.rs | 8 +++-- compiler/rustc_mir_transform/src/coroutine.rs | 18 ++++++++--- .../rustc_mir_transform/src/coroutine/drop.rs | 2 +- ...#0}.coroutine_drop_async.0.panic-abort.mir | 2 ++ ...0}.coroutine_drop_async.0.panic-unwind.mir | 2 ++ 7 files changed, 49 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 8b015e6cecaae..4e858e8b40137 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -872,11 +872,18 @@ pub enum TerminatorKind<'tcx> { /// Marks a suspend point. /// /// Like `Return` terminators in coroutine bodies, this computes `value` and then a - /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to - /// the return place of the function calling this one, and execution continues in the calling - /// function. When next invoked with the same first argument, execution of this function - /// continues at the `resume` basic block, with the second argument written to the `resume_arg` - /// place. If the coroutine is dropped before then, the `drop` basic block is invoked. + /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned + /// to the return place of the function calling this one, and execution continues in the + /// calling function. + /// + /// When the coroutine is polled, execution of this function continues at the `resume` + /// basic block, the `resume_arg` place is evaluated and the second argument to `poll` is + /// written to it. + /// + /// If the coroutine is dropped before then, execution of this function continues at the `drop` + /// basic block and the `resume_arg` place is evaluated. For async drop, the second argument to + /// the destructor `poll` method is written to `resume_arg`. For synchronous drops, + /// uninitialized bytes are written to `resume_arg`. /// /// Note that coroutines can be (unstably) cloned under certain conditions, which means that /// this terminator can **return multiple times**! MIR optimizations that reorder code into @@ -884,8 +891,6 @@ pub enum TerminatorKind<'tcx> { /// See . /// /// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering. - /// - /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`? Yield { /// The value to return. value: Operand<'tcx>, diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 1cd11bbd9ce4f..503fd8a3d6b60 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -674,7 +674,7 @@ impl<'tcx> TerminatorKind<'tcx> { } } -#[derive(Copy, Clone, Debug)] +#[derive(Debug)] pub enum TerminatorEdges<'mir, 'tcx> { /// For terminators that have no successor, like `return`. None, @@ -686,7 +686,7 @@ pub enum TerminatorEdges<'mir, 'tcx> { Double(BasicBlock, BasicBlock), /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { - return_: &'mir [BasicBlock], + return_: Box<[BasicBlock]>, /// The cleanup block, if it exists. cleanup: Option, place: CallReturnPlaces<'mir, 'tcx>, @@ -755,27 +755,21 @@ impl<'tcx> TerminatorKind<'tcx> { TerminatorEdges::Double(real_target, imaginary_target) } - Yield { resume: ref target, drop, resume_arg, value: _ } => { + Yield { resume: target, drop, resume_arg, value: _ } => { TerminatorEdges::AssignOnReturn { - return_: slice::from_ref(target), - cleanup: drop, + return_: [target].into_iter().chain(drop.into_iter()).collect(), + cleanup: None, place: CallReturnPlaces::Yield(resume_arg), } } - Call { - unwind, - destination, - ref target, - func: _, - args: _, - fn_span: _, - call_source: _, - } => TerminatorEdges::AssignOnReturn { - return_: target.as_ref().map(slice::from_ref).unwrap_or_default(), - cleanup: unwind.cleanup_block(), - place: CallReturnPlaces::Call(destination), - }, + Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { + TerminatorEdges::AssignOnReturn { + return_: target.into_iter().collect(), + cleanup: unwind.cleanup_block(), + place: CallReturnPlaces::Call(destination), + } + } InlineAsm { asm_macro: _, @@ -786,7 +780,7 @@ impl<'tcx> TerminatorKind<'tcx> { ref targets, unwind, } => TerminatorEdges::AssignOnReturn { - return_: targets, + return_: targets.to_owned(), cleanup: unwind.cleanup_block(), place: CallReturnPlaces::InlineAsm(operands), }, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index f8d0885a2808f..39df33187d3a9 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -101,11 +101,13 @@ impl Direction for Backward { propagate(pred, &tmp); } - mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == block => { + mir::TerminatorKind::Yield { resume, drop, resume_arg, .. } + if resume == block || drop == Some(block) => + { let mut tmp = exit_state.clone(); analysis.apply_call_return_effect( &mut tmp, - resume, + block, CallReturnPlaces::Yield(resume_arg), ); propagate(pred, &tmp); @@ -275,7 +277,7 @@ impl Direction for Forward { if !return_.is_empty() { analysis.apply_call_return_effect(exit_state, block, place); - for &target in return_ { + for target in return_ { propagate(target, exit_state); } } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 87db4550d4f10..6d32f1251d057 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1302,13 +1302,21 @@ fn create_coroutine_resume_function<'tcx>( enum Operation { Resume, Drop, + AsyncDrop, } impl Operation { fn target_block(self, point: &SuspensionPoint<'_>) -> Option { match self { Operation::Resume => Some(point.resume), - Operation::Drop => point.drop, + Operation::Drop | Operation::AsyncDrop => point.drop, + } + } + + fn resume_place<'tcx>(self, point: &SuspensionPoint<'tcx>) -> Option> { + match self { + Operation::Resume | Operation::AsyncDrop => Some(point.resume_arg), + Operation::Drop => None, } } } @@ -1339,12 +1347,14 @@ fn create_cases<'tcx>( } } - if operation == Operation::Resume && point.resume_arg != CTX_ARG.into() { - // Move the resume argument to the destination place of the `Yield` terminator + // Move the resume argument to the destination place of the `Yield` terminator + if let Some(resume_arg) = operation.resume_place(point) + && resume_arg != CTX_ARG.into() + { statements.push(Statement::new( source_info, StatementKind::Assign(Box::new(( - point.resume_arg, + resume_arg, Rvalue::Use(Operand::Move(CTX_ARG.into()), WithRetag::Yes), ))), )); diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 372f7117a0119..134d37ba4ef47 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -646,7 +646,7 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>( let source_info = SourceInfo::outermost(body.span); - let mut cases = create_cases(&mut body, transform, Operation::Drop); + let mut cases = create_cases(&mut body, transform, Operation::AsyncDrop); cases.insert(0, (CoroutineArgs::UNRESUMED, drop_clean)); diff --git a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir index 0a1cab37427c8..2213160a748f4 100644 --- a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir +++ b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir @@ -86,10 +86,12 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb12: { + _9 = move _2; goto -> bb4; } bb13: { + _13 = move _2; goto -> bb4; } diff --git a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir index 62fbf10356558..ae97c257a0ddb 100644 --- a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir +++ b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir @@ -105,10 +105,12 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb16: { + _9 = move _2; goto -> bb7; } bb17: { + _13 = move _2; goto -> bb7; } From 3f96a45be0c7e62047d2292317e9297944db67ef Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Tue, 26 May 2026 06:19:15 +0000 Subject: [PATCH 14/15] Correct semantics around return place. --- compiler/rustc_middle/src/mir/syntax.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4e858e8b40137..a4edab0f27a76 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -873,8 +873,8 @@ pub enum TerminatorKind<'tcx> { /// /// Like `Return` terminators in coroutine bodies, this computes `value` and then a /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned - /// to the return place of the function calling this one, and execution continues in the - /// calling function. + /// to the return place provided by the caller function, and execution continues in this caller + /// function. /// /// When the coroutine is polled, execution of this function continues at the `resume` /// basic block, the `resume_arg` place is evaluated and the second argument to `poll` is From b5426778730479c1950930e61bf540e00aa29918 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Fri, 29 May 2026 20:05:23 +0000 Subject: [PATCH 15/15] Review nits. --- compiler/rustc_middle/src/mir/syntax.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index a4edab0f27a76..07eaa085fabc9 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -876,14 +876,14 @@ pub enum TerminatorKind<'tcx> { /// to the return place provided by the caller function, and execution continues in this caller /// function. /// - /// When the coroutine is polled, execution of this function continues at the `resume` - /// basic block, the `resume_arg` place is evaluated and the second argument to `poll` is - /// written to it. + /// When the coroutine is resumed/polled, execution of this function continues at the `resume` + /// basic block, the `resume_arg` place is evaluated and the second argument to `resume/poll` + /// is written to it. /// /// If the coroutine is dropped before then, execution of this function continues at the `drop` - /// basic block and the `resume_arg` place is evaluated. For async drop, the second argument to - /// the destructor `poll` method is written to `resume_arg`. For synchronous drops, - /// uninitialized bytes are written to `resume_arg`. + /// basic block and the `resume_arg` place expression is evaluated. For async drop, the second + /// argument to the destructor `resume/poll` method is written to `resume_arg`. For synchronous + /// drops, uninitialized bytes are written to `resume_arg`. /// /// Note that coroutines can be (unstably) cloned under certain conditions, which means that /// this terminator can **return multiple times**! MIR optimizations that reorder code into