From 617d9de4e8d4f0e2c945a6faf2a0e758fba624ab Mon Sep 17 00:00:00 2001 From: Shivendra Sharma Date: Wed, 8 Apr 2026 03:30:00 +0530 Subject: [PATCH 01/14] rustdoc: preserve `doc(cfg)` on locally re-exported type aliases When a type alias is locally re-exported from a private module (an implicit inline), rustdoc drops its `cfg` attributes because it treats it like a standard un-inlined re-export. Since type aliases have no inner fields to carry the `cfg` badge (unlike structs or enums), the portability info is lost entirely. This patch explicitly preserves the target's `cfg` metadata when the generated item is a `TypeAliasItem`, ensuring the portability badge renders correctly without breaking standard cross-crate re-export behavior. --- src/librustdoc/clean/mod.rs | 3 +- .../reexport/type-alias-reexport.rs | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/reexport/type-alias-reexport.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5366a0eca3293..d628889450a0c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -205,7 +205,8 @@ fn generate_item_with_correct_attrs( attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); is_inline = is_inline || import_is_inline; } - add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); + let keep_target_cfg = is_inline || matches!(kind, ItemKind::TypeAliasItem(..)); + add_without_unwanted_attributes(&mut attrs, target_attrs, keep_target_cfg, None); attrs } else { // We only keep the item's attributes. diff --git a/tests/rustdoc-html/reexport/type-alias-reexport.rs b/tests/rustdoc-html/reexport/type-alias-reexport.rs new file mode 100644 index 0000000000000..34e2d7208f88d --- /dev/null +++ b/tests/rustdoc-html/reexport/type-alias-reexport.rs @@ -0,0 +1,32 @@ +// Regression test for . +// This test ensures that auto-generated and explicit `doc(cfg)` attributes are correctly +// preserved for locally re-exported type aliases. + +#![crate_name = "foo"] +#![feature(doc_cfg)] + +mod inner { + #[cfg(target_os = "linux")] + pub type One = u32; + + #[doc(cfg(target_os = "linux"))] + pub type Two = u32; +} + +//@ has 'foo/index.html' +// There should be two items in the type aliases table. +//@ count - '//*[@class="item-table"]/dt' 2 +// Both of them should have the portability badge in the module index. +//@ count - '//*[@class="item-table"]/dt/*[@class="stab portability"]' 2 + +//@ has 'foo/type.One.html' +// Check that the individual type page has the portability badge. +//@ count - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 1 +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 'Linux' + +//@ has 'foo/type.Two.html' +// Check the explicit doc(cfg) type page as well. +//@ count - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 1 +//@ has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' 'Linux' + +pub use self::inner::{One, Two}; From 7c4cf965877567449e901ad9c963ee46ec02641d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 30 Mar 2026 18:14:01 +0200 Subject: [PATCH 02/14] report the `varargs_without_pattern` lint in deps --- compiler/rustc_lint_defs/src/builtin.rs | 9 ++- tests/ui/c-variadic/parse-errors.e2015.stderr | 57 ++++++++++++++ tests/ui/c-variadic/parse-errors.e2018.stderr | 76 +++++++++++++++++++ tests/ui/thir-print/c-variadic.stderr | 12 +++ 4 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 tests/ui/thir-print/c-variadic.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 4aff294aeac61..2079162e781d7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -5558,7 +5558,8 @@ declare_lint! { /// /// ### Example /// - /// ```rust + #[cfg_attr(bootstrap, doc = "```rust")] + #[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")] /// // Using `...` in non-foreign function definitions is unstable, however stability is /// // currently only checked after attributes are expanded, so using `#[cfg(false)]` here will /// // allow this to compile on stable Rust. @@ -5566,7 +5567,7 @@ declare_lint! { /// fn foo(...) { /// /// } - /// ``` + #[doc = "```"] /// /// {{produces}} /// @@ -5590,10 +5591,10 @@ declare_lint! { /// /// [future-incompatible]: ../index.md#future-incompatible-lints pub VARARGS_WITHOUT_PATTERN, - Warn, + Deny, "detects usage of `...` arguments without a pattern in non-foreign items", @future_incompatible = FutureIncompatibleInfo { reason: fcw!(FutureReleaseError #145544), - report_in_deps: false, + report_in_deps: true, }; } diff --git a/tests/ui/c-variadic/parse-errors.e2015.stderr b/tests/ui/c-variadic/parse-errors.e2015.stderr index de9362c4380de..e4939cb4b0e91 100644 --- a/tests/ui/c-variadic/parse-errors.e2015.stderr +++ b/tests/ui/c-variadic/parse-errors.e2015.stderr @@ -44,3 +44,60 @@ LL | unsafe extern "C" fn f(_: ...) {} error: aborting due to 3 previous errors +Future incompatibility report: Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:11:28 + | +LL | unsafe extern "C" fn f(...) { + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) { + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:14:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:20:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + diff --git a/tests/ui/c-variadic/parse-errors.e2018.stderr b/tests/ui/c-variadic/parse-errors.e2018.stderr index a7d5f79bf1339..eac0f6f07311a 100644 --- a/tests/ui/c-variadic/parse-errors.e2018.stderr +++ b/tests/ui/c-variadic/parse-errors.e2018.stderr @@ -57,3 +57,79 @@ LL | unsafe extern "C" fn f(_: ...) {} error: aborting due to 4 previous errors +Future incompatibility report: Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:11:28 + | +LL | unsafe extern "C" fn f(...) { + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) { + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:14:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:20:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/parse-errors.rs:26:32 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 +note: the lint level is defined here + --> $DIR/parse-errors.rs:7:9 + | +LL | #![deny(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + diff --git a/tests/ui/thir-print/c-variadic.stderr b/tests/ui/thir-print/c-variadic.stderr new file mode 100644 index 0000000000000..a4050695944d4 --- /dev/null +++ b/tests/ui/thir-print/c-variadic.stderr @@ -0,0 +1,12 @@ +Future incompatibility report: Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/c-variadic.rs:7:34 + | +LL | unsafe extern "C" fn foo(_: i32, ...) {} + | ^^^ + | +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn foo(_: i32, _: ...) {} + | ++ + From 3c0d5f001927646220a09c382f912b07b33a49db Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 17 Oct 2025 15:28:21 +0200 Subject: [PATCH 03/14] naked functions: respect `function_sections` on windows For `gnu` function_sections is off by default. --- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 9 ++- .../codegen-llvm/naked-fn/naked-functions.rs | 66 +++++++++++-------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 97cfc648b7cb0..e9dc28dca0142 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -128,6 +128,8 @@ fn prefix_and_suffix<'tcx>( let is_arm = tcx.sess.target.arch == Arch::Arm; let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode); + let function_sections = + tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections); // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden @@ -278,8 +280,11 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".type 32").unwrap(); writeln!(begin, ".endef").unwrap(); - let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}")); - writeln!(begin, ".pushsection {},\"xr\"", section).unwrap(); + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},\"xr\"").unwrap() + } else if function_sections { + writeln!(begin, ".pushsection .text${asm_name},\"xr\"").unwrap() + } write_linkage(&mut begin).unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); writeln!(begin, "{asm_name}:").unwrap(); diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index b5c84ede8f063..3243ef8135047 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -1,12 +1,14 @@ //@ add-minicore -//@ revisions: linux win_x86 win_i686 macos thumb +//@ revisions: linux win_x86_msvc win_x86_gnu win_i686_gnu macos thumb // //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 -//@[win_x86] compile-flags: --target x86_64-pc-windows-gnu -//@[win_x86] needs-llvm-components: x86 -//@[win_i686] compile-flags: --target i686-pc-windows-gnu -//@[win_i686] needs-llvm-components: x86 +//@[win_x86_gnu] compile-flags: --target x86_64-pc-windows-gnu +//@[win_x86_gnu] needs-llvm-components: x86 +//@[win_x86_msvc] compile-flags: --target x86_64-pc-windows-msvc +//@[win_x86_msvc] needs-llvm-components: x86 +//@[win_i686_gnu] compile-flags: --target i686-pc-windows-gnu +//@[win_i686_gnu] needs-llvm-components: x86 //@[macos] compile-flags: --target aarch64-apple-darwin //@[macos] needs-llvm-components: aarch64 //@[thumb] compile-flags: --target thumbv7em-none-eabi @@ -23,6 +25,11 @@ use minicore::*; // // linux: .pushsection .text.naked_empty,\22ax\22, @progbits // macos: .pushsection __TEXT,__text,regular,pure_instructions +// +// win_x86_msvc: .pushsection .text$naked_empty,\22xr\22 +// win_x86_gnu-NOT: .pushsection +// win_i686_gnu-NOT: .pushsection +// // thumb: .pushsection .text.naked_empty,\22ax\22, %progbits // // linux, macos, thumb: .balign 4 @@ -35,12 +42,12 @@ use minicore::*; // // linux: .type naked_empty, @function // -// win_x86: .def naked_empty -// win_i686: .def _naked_empty +// win_x86_msvc,win_x86_gnu: .def naked_empty +// win_i686_gnu: .def _naked_empty // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // // win_x86: .pushsection .text.naked_empty,\22xr\22 // win_i686: .pushsection .text._naked_empty,\22xr\22 @@ -59,7 +66,8 @@ use minicore::*; // linux,macos,win_x86,win_x86: ret // thumb: bx lr // -// linux,macos,thumb: .popsection +// linux,windows,win_x86_msvc,thumb: .popsection +// win_x86_gnu-NOT,win_i686_gnu-NOT: .popsection // // thumb: .thumb // @@ -82,6 +90,11 @@ pub extern "C" fn naked_empty() { // // linux: .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits // macos: .pushsection __TEXT,__text,regular,pure_instructions +// +// win_x86_msvc: .pushsection .text$naked_with_args_and_return,\22xr\22 +// win_x86_gnu-NOT: .pushsection +// win_i686_gnu-NOT: .pushsection +// // thumb: .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits // // linux, macos, thumb: .balign 4 @@ -94,12 +107,12 @@ pub extern "C" fn naked_empty() { // // linux: .type naked_with_args_and_return, @function // -// win_x86: .def naked_with_args_and_return -// win_i686: .def _naked_with_args_and_return +// win_x86_msvc,win_x86_gnu: .def naked_with_args_and_return +// win_i686_gnu: .def _naked_with_args_and_return // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // // win_x86: .pushsection .text.naked_with_args_and_return,\22xr\22 // win_i686: .pushsection .text._naked_with_args_and_return,\22xr\22 @@ -115,14 +128,15 @@ pub extern "C" fn naked_empty() { // // CHECK-LABEL: naked_with_args_and_return: // -// linux, win_x86,win_i686: lea rax, [rdi + rsi] +// linux,win_x86_msvc,win_x86_gnu,win_i686_gnu: lea rax, [rdi + rsi] // macos: add x0, x0, x1 // thumb: adds r0, r0, r1 // // linux,macos,win_x86,win_i686: ret // thumb: bx lr // -// linux,macos,thumb: .popsection +// linux,windows,win_x86_msvc,thumb: .popsection +// win_x86_gnu-NOT,win_i686_gnu-NOT: .popsection // // thumb: .thumb // @@ -146,7 +160,7 @@ pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { // linux: .pushsection .text.some_different_name,\22ax\22, @progbits // macos: .pushsection .text.some_different_name,regular,pure_instructions -// win_x86,win_i686: .pushsection .text.some_different_name,\22xr\22 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .pushsection .text.some_different_name,\22xr\22 // thumb: .pushsection .text.some_different_name,\22ax\22, %progbits // CHECK-LABEL: test_link_section: #[no_mangle] @@ -163,15 +177,15 @@ pub extern "C" fn test_link_section() { } } -// win_x86: .def fastcall_cc -// win_i686: .def @fastcall_cc@4 +// win_x86_msvc,win_x86_gnu: .def fastcall_cc +// win_i686_gnu: .def @fastcall_cc@4 // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // -// win_x86-LABEL: fastcall_cc: -// win_i686-LABEL: @fastcall_cc@4: +// win_x86_msvc-LABEL,win_x86_gnu-LABEL: fastcall_cc: +// win_i686_gnu-LABEL: @fastcall_cc@4: #[cfg(target_os = "windows")] #[no_mangle] #[unsafe(naked)] From b446476f5279ea62fb2098395cc950573db8ab81 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 17 Oct 2025 15:54:41 +0200 Subject: [PATCH 04/14] naked functions: respect `function_sections` on linux/macos --- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 22 +++++++++++++------ .../codegen-llvm/naked-fn/naked-functions.rs | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index e9dc28dca0142..4589ddbc3e2e7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -220,8 +220,6 @@ fn prefix_and_suffix<'tcx>( let mut end = String::new(); match asm_binary_format { BinaryFormat::Elf => { - let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}")); - let progbits = match is_arm { true => "%progbits", false => "@progbits", @@ -232,7 +230,11 @@ fn prefix_and_suffix<'tcx>( false => "@function", }; - writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); + } else if function_sections { + writeln!(begin, ".pushsection .text.{asm_name},\"ax\", {progbits}").unwrap(); + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); match visibility { @@ -251,14 +253,18 @@ fn prefix_and_suffix<'tcx>( // pattern match on assembly generated by LLVM. writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); writeln!(end, ".size {asm_name}, . - {asm_name}").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() || function_sections { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } } BinaryFormat::MachO => { - let section = link_section.unwrap_or_else(|| "__TEXT,__text".to_string()); - writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap(); + // NOTE: LLVM ignores `-Zfunction-sections` on macos. + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},regular,pure_instructions").unwrap(); + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); match visibility { @@ -269,7 +275,9 @@ fn prefix_and_suffix<'tcx>( writeln!(end).unwrap(); writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index 3243ef8135047..e83a62498bc57 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -24,7 +24,7 @@ use minicore::*; // linux,win_x86,win_i686: .intel_syntax // // linux: .pushsection .text.naked_empty,\22ax\22, @progbits -// macos: .pushsection __TEXT,__text,regular,pure_instructions +// macos-NOT: .pushsection // // win_x86_msvc: .pushsection .text$naked_empty,\22xr\22 // win_x86_gnu-NOT: .pushsection @@ -89,7 +89,7 @@ pub extern "C" fn naked_empty() { // linux,win_x86,win_i686: .intel_syntax // // linux: .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits -// macos: .pushsection __TEXT,__text,regular,pure_instructions +// macos-NOT: .pushsection // // win_x86_msvc: .pushsection .text$naked_with_args_and_return,\22xr\22 // win_x86_gnu-NOT: .pushsection From 22531e4f617d637dbd73cd88a3af1d4f83a1d7a1 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 17 Oct 2025 16:38:35 +0200 Subject: [PATCH 05/14] naked functions: add run-make test for DCE --- .../naked-dead-code-elimination/main.rs | 24 +++++++++++++++++++ .../naked-dead-code-elimination/rmake.rs | 10 ++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/run-make/naked-dead-code-elimination/main.rs create mode 100644 tests/run-make/naked-dead-code-elimination/rmake.rs diff --git a/tests/run-make/naked-dead-code-elimination/main.rs b/tests/run-make/naked-dead-code-elimination/main.rs new file mode 100644 index 0000000000000..d0a518630179f --- /dev/null +++ b/tests/run-make/naked-dead-code-elimination/main.rs @@ -0,0 +1,24 @@ +use std::arch::naked_asm; + +#[unsafe(naked)] +#[unsafe(no_mangle)] +extern "C" fn used() { + naked_asm!("ret") +} + +#[unsafe(naked)] +#[unsafe(no_mangle)] +extern "C" fn unused() { + naked_asm!("ret") +} + +#[unsafe(naked)] +#[unsafe(link_section = "foobar")] +#[unsafe(no_mangle)] +extern "C" fn unused_link_section() { + naked_asm!("ret") +} + +fn main() { + used(); +} diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs new file mode 100644 index 0000000000000..1e1256f55b0fa --- /dev/null +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -0,0 +1,10 @@ +//@ needs-asm-support + +use run_make_support::symbols::object_contains_any_symbol; +use run_make_support::{bin_name, rustc}; + +fn main() { + rustc().input("main.rs").opt().run(); + let mut unused = vec!["unused", "unused_link_section"]; + assert!(!object_contains_any_symbol(bin_name("main"), &unused)); +} From 31bdf2db9a93305857771af0f4d77174a909ed18 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 17 Jan 2026 13:30:47 +0100 Subject: [PATCH 06/14] naked-functions: properly document the -Zfunction-sections windows status --- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 32 +++++++++++--- .../codegen-llvm/naked-fn/naked-functions.rs | 42 ++++++++++++------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 4589ddbc3e2e7..941267e4eceae 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, ty}; use rustc_span::sym; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; -use rustc_target::spec::{Arch, BinaryFormat}; +use rustc_target::spec::{Arch, BinaryFormat, Env}; use crate::common; use crate::mir::AsmCodegenMethods; @@ -234,6 +234,8 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); } else if function_sections { writeln!(begin, ".pushsection .text.{asm_name},\"ax\", {progbits}").unwrap(); + } else { + writeln!(begin, ".text").unwrap(); } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); @@ -261,7 +263,9 @@ fn prefix_and_suffix<'tcx>( } } BinaryFormat::MachO => { - // NOTE: LLVM ignores `-Zfunction-sections` on macos. + // NOTE: LLVM ignores `-Zfunction-sections` on macos. Instead the Mach-O symbol + // subsection splitting feature is used, which can be enabled with the + // `.subsections_via_symbols` global directive. LLVM already enables this directive. if let Some(section) = &link_section { writeln!(begin, ".pushsection {section},regular,pure_instructions").unwrap(); } @@ -289,9 +293,27 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".endef").unwrap(); if let Some(section) = &link_section { - writeln!(begin, ".pushsection {section},\"xr\"").unwrap() - } else if function_sections { - writeln!(begin, ".pushsection .text${asm_name},\"xr\"").unwrap() + writeln!(begin, ".section {section},\"xr\"").unwrap() + } else if !function_sections { + // Function sections are enabled by default on MSVC, but disabled by default on GNU. + writeln!(begin, ".text").unwrap(); + } else { + // LLVM uses an extension to the section directive to support defining multiple + // sections with the same name and comdat. It adds `unique,` at the end of the + // `.section` directive. We have no way of generating that unique ID here, so don't + // emit it. + // + // See https://llvm.org/docs/Extensions.html#id2. + match &tcx.sess.target.options.env { + Env::Gnu => { + writeln!(begin, ".section .text${asm_name},\"xr\",one_only,{asm_name}") + .unwrap(); + } + Env::Msvc => { + writeln!(begin, ".section .text,\"xr\",one_only,{asm_name}").unwrap(); + } + other => bug!("invalid coff env {other:?}"), + } } write_linkage(&mut begin).unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index e83a62498bc57..a782ab5310e34 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -1,10 +1,17 @@ +// ignore-tidy-linelength +// //@ add-minicore -//@ revisions: linux win_x86_msvc win_x86_gnu win_i686_gnu macos thumb +//@ revisions: linux linux_no_function_sections macos thumb +//@ revisions: win_x86_msvc win_x86_gnu win_i686_gnu win_x86_gnu_function_sections // //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 +//@[linux_no_function_sections] compile-flags: --target x86_64-unknown-linux-gnu -Zfunction-sections=false +//@[linux_no_function_sections] needs-llvm-components: x86 //@[win_x86_gnu] compile-flags: --target x86_64-pc-windows-gnu //@[win_x86_gnu] needs-llvm-components: x86 +//@[win_x86_gnu_function_sections] compile-flags: --target x86_64-pc-windows-gnu -Zfunction-sections +//@[win_x86_gnu_function_sections] needs-llvm-components: x86 //@[win_x86_msvc] compile-flags: --target x86_64-pc-windows-msvc //@[win_x86_msvc] needs-llvm-components: x86 //@[win_i686_gnu] compile-flags: --target i686-pc-windows-gnu @@ -21,20 +28,22 @@ extern crate minicore; use minicore::*; -// linux,win_x86,win_i686: .intel_syntax +// linux,win_x86_gnu,win_i686_gnu: .intel_syntax // // linux: .pushsection .text.naked_empty,\22ax\22, @progbits +// linux_no_function_sections: .text // macos-NOT: .pushsection // -// win_x86_msvc: .pushsection .text$naked_empty,\22xr\22 -// win_x86_gnu-NOT: .pushsection -// win_i686_gnu-NOT: .pushsection +// win_x86_msvc: .section .text,\22xr\22,one_only,naked_empty +// win_x86_gnu_function_sections: .section .text$naked_empty,\22xr\22,one_only,naked_empty +// win_x86_gnu-NOT: .section +// win_i686_gnu-NOT: .section // // thumb: .pushsection .text.naked_empty,\22ax\22, %progbits // // linux, macos, thumb: .balign 4 // -// linux,thumb: .globl naked_empty +// linux,win_x86_gnu,thumb: .globl naked_empty // macos: .globl _naked_empty // // CHECK-NOT: .private_extern @@ -63,7 +72,7 @@ use minicore::*; // // CHECK-LABEL: naked_empty: // -// linux,macos,win_x86,win_x86: ret +// linux,macos,win_x86_msvc,win_x86_gnu,win_i686_gnu: ret // thumb: bx lr // // linux,windows,win_x86_msvc,thumb: .popsection @@ -86,20 +95,22 @@ pub extern "C" fn naked_empty() { } } -// linux,win_x86,win_i686: .intel_syntax +// linux,win_x86_gnu,win_i686_gnu,win_x86_msvc: .intel_syntax // // linux: .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits +// linux_no_function_sections: .text // macos-NOT: .pushsection // -// win_x86_msvc: .pushsection .text$naked_with_args_and_return,\22xr\22 -// win_x86_gnu-NOT: .pushsection -// win_i686_gnu-NOT: .pushsection +// win_x86_msvc: .section .text,\22xr\22,one_only,naked_with_args_and_return +// win_x86_gnu_function_sections: .section .text$naked_with_args_and_return,\22xr\22,one_only,naked_with_args_and_return +// win_x86_gnu-NOT: .section +// win_i686_gnu-NOT: .section // // thumb: .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits // // linux, macos, thumb: .balign 4 // -// linux,thumb: .globl naked_with_args_and_return +// linux,win_x86_gnu,win_x86_msvc,win_i686_gnu,thumb: .globl naked_with_args_and_return // macos: .globl _naked_with_args_and_return // // CHECK-NOT: .private_extern @@ -132,7 +143,7 @@ pub extern "C" fn naked_empty() { // macos: add x0, x0, x1 // thumb: adds r0, r0, r1 // -// linux,macos,win_x86,win_i686: ret +// linux,macos,win_x86_msvc,win_x86_gnu,win_i686_gnu: ret // thumb: bx lr // // linux,windows,win_x86_msvc,thumb: .popsection @@ -158,9 +169,10 @@ pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { } } -// linux: .pushsection .text.some_different_name,\22ax\22, @progbits +// linux,linux_no_function_sections: .pushsection .text.some_different_name,\22ax\22, @progbits // macos: .pushsection .text.some_different_name,regular,pure_instructions -// win_x86_msvc,win_x86_gnu,win_i686_gnu: .pushsection .text.some_different_name,\22xr\22 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .section .text.some_different_name,\22xr\22 +// win_x86_gnu_function_sections: .section .text.some_different_name,\22xr\22 // thumb: .pushsection .text.some_different_name,\22ax\22, %progbits // CHECK-LABEL: test_link_section: #[no_mangle] From 3ce3436fd6504c6d34760608d6f85159714343f0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 15 Apr 2026 14:56:59 +1000 Subject: [PATCH 07/14] Disallow ZST allocations with `TypedArena`. `DroplessArena::alloc` already disallows ZST allocation. `TypedArena::alloc` allows it but: - (a) it's never used, and - (b) writing to `NonNull::dangling()` seems dubious, even if the write is zero-sized. This commit just changes it to panic on a ZST. This eliminates an untested code path, and we shouldn't be allocating ZSTs anyway. It also eliminates an unused ZST code path in `clear_last_chunk`. Tests are also updated accordingly. --- compiler/rustc_arena/src/lib.rs | 36 +++++++++++-------------------- compiler/rustc_arena/src/tests.rs | 18 +++------------- 2 files changed, 15 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 0785942d13a38..24ade7300c33b 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -140,25 +140,19 @@ impl TypedArena { /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] pub fn alloc(&self, object: T) -> &mut T { + assert!(size_of::() != 0); + if self.ptr == self.end { self.grow(1) } unsafe { - if size_of::() == 0 { - self.ptr.set(self.ptr.get().wrapping_byte_add(1)); - let ptr = ptr::NonNull::::dangling().as_ptr(); - // Don't drop the object. This `write` is equivalent to `forget`. - ptr::write(ptr, object); - &mut *ptr - } else { - let ptr = self.ptr.get(); - // Advance the pointer. - self.ptr.set(self.ptr.get().add(1)); - // Write into uninitialized memory. - ptr::write(ptr, object); - &mut *ptr - } + let ptr = self.ptr.get(); + // Advance the pointer. + self.ptr.set(self.ptr.get().add(1)); + // Write into uninitialized memory. + ptr::write(ptr, object); + &mut *ptr } } @@ -302,16 +296,10 @@ impl TypedArena { let end = self.ptr.get().addr(); // We then calculate the number of elements to be dropped in the last chunk, // which is the filled area's length. - let diff = if size_of::() == 0 { - // `T` is ZST. It can't have a drop flag, so the value here doesn't matter. We get - // the number of zero-sized values in the last and only chunk, just out of caution. - // Recall that `end` was incremented for each allocated value. - end - start - } else { - // FIXME: this should *likely* use `offset_from`, but more - // investigation is needed (including running tests in miri). - (end - start) / size_of::() - }; + assert_ne!(size_of::(), 0); + // FIXME: this should *likely* use `offset_from`, but more + // investigation is needed (including running tests in miri). + let diff = (end - start) / size_of::(); // Pass that to the `destroy` method. unsafe { last_chunk.destroy(diff); diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs index eb9406d691b10..751ddd80408a8 100644 --- a/compiler/rustc_arena/src/tests.rs +++ b/compiler/rustc_arena/src/tests.rs @@ -22,7 +22,6 @@ impl TypedArena { if let Some(last_chunk) = chunks_borrow.last_mut() { self.clear_last_chunk(last_chunk); let len = chunks_borrow.len(); - // If `T` is ZST, code below has no effect. for mut chunk in chunks_borrow.drain(..len - 1) { chunk.destroy(chunk.entries); } @@ -117,18 +116,6 @@ fn test_noncopy() { } } -#[test] -fn test_typed_arena_zero_sized() { - let arena = TypedArena::default(); - #[cfg(not(miri))] - const N: usize = 100000; - #[cfg(miri)] - const N: usize = 1000; - for _ in 0..N { - arena.alloc(()); - } -} - #[test] fn test_typed_arena_clear() { let mut arena = TypedArena::default(); @@ -207,7 +194,8 @@ thread_local! { static DROP_COUNTER: Cell = Cell::new(0) } -struct SmallDroppable; +#[allow(unused)] +struct SmallDroppable(u8); impl Drop for SmallDroppable { fn drop(&mut self) { @@ -222,7 +210,7 @@ fn test_typed_arena_drop_small_count() { let arena: TypedArena = TypedArena::default(); for _ in 0..100 { // Allocate something with drop glue to make sure it doesn't leak. - arena.alloc(SmallDroppable); + arena.alloc(SmallDroppable(0)); } // dropping }; From 55ba521015a9117bc5ca72320b034f0a8cc2bf9c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 30 Mar 2026 00:44:56 +0200 Subject: [PATCH 08/14] fix macho section specifier & windows test --- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 3 ++- .../src/external_deps/rustc.rs | 10 ++++++++++ .../naked-dead-code-elimination/main.rs | 20 ++++++++++++++++++- .../naked-dead-code-elimination/rmake.rs | 18 ++++++++++++++--- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 941267e4eceae..c94376c7673da 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -295,7 +295,8 @@ fn prefix_and_suffix<'tcx>( if let Some(section) = &link_section { writeln!(begin, ".section {section},\"xr\"").unwrap() } else if !function_sections { - // Function sections are enabled by default on MSVC, but disabled by default on GNU. + // Function sections are enabled by default on MSVC and windows-gnullvm, + // but disabled by default on GNU. writeln!(begin, ".text").unwrap(); } else { // LLVM uses an extension to the section directive to support defining multiple diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 2fa680a8e2334..e8645e00e1852 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -449,6 +449,16 @@ impl Rustc { self.cmd.arg("-Zcodegen-source-order"); self } + + /// Specify `-Z function-sections={yes, no}`. + pub fn function_sections(&mut self, enable: bool) -> &mut Self { + let flag = match enable { + true => "-Zfunction-sections=yes", + false => "-Zfunction-sections=no", + }; + self.cmd.arg(flag); + self + } } /// Query the sysroot path corresponding `rustc --print=sysroot`. diff --git a/tests/run-make/naked-dead-code-elimination/main.rs b/tests/run-make/naked-dead-code-elimination/main.rs index d0a518630179f..83da62d314587 100644 --- a/tests/run-make/naked-dead-code-elimination/main.rs +++ b/tests/run-make/naked-dead-code-elimination/main.rs @@ -1,3 +1,4 @@ +#![feature(cfg_target_object_format)] use std::arch::naked_asm; #[unsafe(naked)] @@ -6,6 +7,11 @@ extern "C" fn used() { naked_asm!("ret") } +#[unsafe(no_mangle)] +extern "C" fn unused_clothed() -> i32 { + 42 +} + #[unsafe(naked)] #[unsafe(no_mangle)] extern "C" fn unused() { @@ -13,12 +19,24 @@ extern "C" fn unused() { } #[unsafe(naked)] -#[unsafe(link_section = "foobar")] +#[unsafe(link_section = cfg_select!( + target_object_format = "mach-o" => "__TEXT,foobar", + _ => ".foobar", +))] #[unsafe(no_mangle)] extern "C" fn unused_link_section() { naked_asm!("ret") } +#[unsafe(link_section = cfg_select!( + target_object_format = "mach-o" => "__TEXT,baz", + _ => ".baz", +))] +#[unsafe(no_mangle)] +extern "C" fn unused_link_section_clothed() -> i32 { + 43 +} + fn main() { used(); } diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs index 1e1256f55b0fa..a29212084b127 100644 --- a/tests/run-make/naked-dead-code-elimination/rmake.rs +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -4,7 +4,19 @@ use run_make_support::symbols::object_contains_any_symbol; use run_make_support::{bin_name, rustc}; fn main() { - rustc().input("main.rs").opt().run(); - let mut unused = vec!["unused", "unused_link_section"]; - assert!(!object_contains_any_symbol(bin_name("main"), &unused)); + rustc().input("main.rs").opt().function_sections(true).run(); + + let bin = bin_name("main"); + + // Check that the naked symbol is eliminated when the "clothed" one is. + + assert_eq!( + object_contains_any_symbol(&bin, &["unused_clothed"]), + object_contains_any_symbol(&bin, &["unused"]) + ); + + assert_eq!( + object_contains_any_symbol(&bin, &["unused_link_section_clothed"]), + object_contains_any_symbol(&bin, &["unused_link_section"]) + ); } From 82545d7d797fb1a36111a26066456a93d4fea654 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 15 Apr 2026 14:16:18 +0200 Subject: [PATCH 09/14] Add regression test --- tests/ui/transmute/raw-ptr-non-null.rs | 11 +++++++++++ tests/ui/transmute/raw-ptr-non-null.stderr | 12 ++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/ui/transmute/raw-ptr-non-null.rs create mode 100644 tests/ui/transmute/raw-ptr-non-null.stderr diff --git a/tests/ui/transmute/raw-ptr-non-null.rs b/tests/ui/transmute/raw-ptr-non-null.rs new file mode 100644 index 0000000000000..6e60a6db0eb3e --- /dev/null +++ b/tests/ui/transmute/raw-ptr-non-null.rs @@ -0,0 +1,11 @@ +//! After the use of pattern types inside `NonNull`, +//! transmuting between a niche optimized enum wrapping a +//! generic `NonNull` and raw pointers stopped working. + +use std::ptr::NonNull; +pub const fn is_null<'a, T: ?Sized>(ptr: *const T) -> bool { + unsafe { matches!(core::mem::transmute::<*const T, Option>>(ptr), None) } + //~^ ERROR: cannot transmute +} + +fn main() {} diff --git a/tests/ui/transmute/raw-ptr-non-null.stderr b/tests/ui/transmute/raw-ptr-non-null.stderr new file mode 100644 index 0000000000000..0e3993da89786 --- /dev/null +++ b/tests/ui/transmute/raw-ptr-non-null.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/raw-ptr-non-null.rs:7:23 + | +LL | unsafe { matches!(core::mem::transmute::<*const T, Option>>(ptr), None) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `*const T` (pointer to `T`) + = note: target type: `Option>` (size can vary because of ::Metadata) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0512`. From 8d642647bd32c4f1566086e19ac7192484d9b2eb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 15 Apr 2026 14:26:06 +0200 Subject: [PATCH 10/14] Handle non-null pattern types in size skeleton --- compiler/rustc_middle/src/ty/layout.rs | 17 +++++++++++++++-- tests/ui/transmute/raw-ptr-non-null.rs | 2 +- tests/ui/transmute/raw-ptr-non-null.stderr | 12 ------------ 3 files changed, 16 insertions(+), 15 deletions(-) delete mode 100644 tests/ui/transmute/raw-ptr-non-null.stderr diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 969d654941800..f04b4873f395c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -508,8 +508,21 @@ impl<'tcx> SizeSkeleton<'tcx> { } } - // Pattern types are always the same size as their base. - ty::Pat(base, _) => SizeSkeleton::compute(base, tcx, typing_env), + ty::Pat(base, pat) => { + // Pattern types are always the same size as their base. + let base = SizeSkeleton::compute(base, tcx, typing_env); + match *pat { + ty::PatternKind::Range { .. } | ty::PatternKind::Or(_) => base, + // But in the case of `!null` patterns we need to note that in the + // raw pointer. + ty::PatternKind::NotNull => match base? { + SizeSkeleton::Known(..) | SizeSkeleton::Generic(_) => base, + SizeSkeleton::Pointer { non_zero: _, tail } => { + Ok(SizeSkeleton::Pointer { non_zero: true, tail }) + } + }, + } + } _ => Err(err), } diff --git a/tests/ui/transmute/raw-ptr-non-null.rs b/tests/ui/transmute/raw-ptr-non-null.rs index 6e60a6db0eb3e..af518095b3fbd 100644 --- a/tests/ui/transmute/raw-ptr-non-null.rs +++ b/tests/ui/transmute/raw-ptr-non-null.rs @@ -1,11 +1,11 @@ //! After the use of pattern types inside `NonNull`, //! transmuting between a niche optimized enum wrapping a //! generic `NonNull` and raw pointers stopped working. +//@ check-pass use std::ptr::NonNull; pub const fn is_null<'a, T: ?Sized>(ptr: *const T) -> bool { unsafe { matches!(core::mem::transmute::<*const T, Option>>(ptr), None) } - //~^ ERROR: cannot transmute } fn main() {} diff --git a/tests/ui/transmute/raw-ptr-non-null.stderr b/tests/ui/transmute/raw-ptr-non-null.stderr deleted file mode 100644 index 0e3993da89786..0000000000000 --- a/tests/ui/transmute/raw-ptr-non-null.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/raw-ptr-non-null.rs:7:23 - | -LL | unsafe { matches!(core::mem::transmute::<*const T, Option>>(ptr), None) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: source type: `*const T` (pointer to `T`) - = note: target type: `Option>` (size can vary because of ::Metadata) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0512`. From e910c38861f5bd75946b96040e2611084e6501cb Mon Sep 17 00:00:00 2001 From: Balt <59123926+balt-dev@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:32:54 -0500 Subject: [PATCH 11/14] Add push_mut to release notes --- RELEASES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index c1cf337ea8d2a..1ceb40b872af5 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -78,6 +78,12 @@ Stabilized APIs - [`<*const T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked) - [`<*mut T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1) - [`<*mut T>::as_mut_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked) +- [`Vec::push_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.push_mut) +- [`VecDeque::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_front_mut) +- [`VecDeque::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_back_mut) +- [`VecDeque::insert_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.insert_mut) +- [`LinkedList::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_front_mut) +- [`LinkedList::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_back_mut) These previously stable APIs are now stable in const contexts: From fba9ef8702763b1149866247b673a8de42c59e26 Mon Sep 17 00:00:00 2001 From: Balt <59123926+balt-dev@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:38:59 -0500 Subject: [PATCH 12/14] Add insert_mut to release notes Co-authored-by: Josh Stone --- RELEASES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASES.md b/RELEASES.md index 1ceb40b872af5..d69fea0f0bf64 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -79,6 +79,7 @@ Stabilized APIs - [`<*mut T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1) - [`<*mut T>::as_mut_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked) - [`Vec::push_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.push_mut) +- [`Vec::insert_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.insert_mut) - [`VecDeque::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_front_mut) - [`VecDeque::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_back_mut) - [`VecDeque::insert_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.insert_mut) From 4095bbdd2d99a217f6b60ffbece3d72ba6204d4f Mon Sep 17 00:00:00 2001 From: Balt <59123926+balt-dev@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:48:40 -0500 Subject: [PATCH 13/14] Add new Layout methods to release notes --- RELEASES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index d69fea0f0bf64..27b4fe36136c1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -85,6 +85,10 @@ Stabilized APIs - [`VecDeque::insert_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.insert_mut) - [`LinkedList::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_front_mut) - [`LinkedList::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_back_mut) +- [`Layout::danging_ptr`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.danging_ptr) +- [`Layout::repeat`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat) +- [`Layout::repeat_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat_packed) +- [`Layout::extend_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.extend_packed) These previously stable APIs are now stable in const contexts: From d87a2e7ddd74e80a7d1358fa7dc70553eb4e58c6 Mon Sep 17 00:00:00 2001 From: Balt <59123926+balt-dev@users.noreply.github.com> Date: Wed, 15 Apr 2026 11:56:45 -0500 Subject: [PATCH 14/14] Fix typo for danging_ptr Co-authored-by: Josh Stone --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 27b4fe36136c1..32d7b4add8c0a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -85,7 +85,7 @@ Stabilized APIs - [`VecDeque::insert_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.insert_mut) - [`LinkedList::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_front_mut) - [`LinkedList::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_back_mut) -- [`Layout::danging_ptr`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.danging_ptr) +- [`Layout::dangling_ptr`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.dangling_ptr) - [`Layout::repeat`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat) - [`Layout::repeat_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat_packed) - [`Layout::extend_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.extend_packed)