Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
617d9de
rustdoc: preserve `doc(cfg)` on locally re-exported type aliases
shivendra02467 Apr 7, 2026
7c4cf96
report the `varargs_without_pattern` lint in deps
folkertdev Mar 30, 2026
3c0d5f0
naked functions: respect `function_sections` on windows
folkertdev Oct 17, 2025
b446476
naked functions: respect `function_sections` on linux/macos
folkertdev Oct 17, 2025
22531e4
naked functions: add run-make test for DCE
folkertdev Oct 17, 2025
31bdf2d
naked-functions: properly document the -Zfunction-sections windows st…
folkertdev Jan 17, 2026
3ce3436
Disallow ZST allocations with `TypedArena`.
nnethercote Apr 15, 2026
55ba521
fix macho section specifier & windows test
folkertdev Mar 29, 2026
82545d7
Add regression test
oli-obk Apr 15, 2026
8d64264
Handle non-null pattern types in size skeleton
oli-obk Apr 15, 2026
e910c38
Add push_mut to release notes
balt-dev Apr 15, 2026
fba9ef8
Add insert_mut to release notes
balt-dev Apr 15, 2026
4095bbd
Add new Layout methods to release notes
balt-dev Apr 15, 2026
d87a2e7
Fix typo for danging_ptr
balt-dev Apr 15, 2026
36da15f
Rollup merge of #147811 - folkertdev:naked-function-sections, r=Amanieu
matthiaskrgr Apr 15, 2026
dbfb9cd
Rollup merge of #154599 - folkertdev:varargs-without-pattern-in-deps,…
matthiaskrgr Apr 15, 2026
c812064
Rollup merge of #154970 - shivendra02467:fix-rustdoc-154921, r=Guilla…
matthiaskrgr Apr 15, 2026
cbd9361
Rollup merge of #155326 - nnethercote:disallow-ZST-TypedArena, r=Nadr…
matthiaskrgr Apr 15, 2026
eddad5f
Rollup merge of #155340 - oli-obk:size-skeleton-pat-tys, r=mati865
matthiaskrgr Apr 15, 2026
f1e9c98
Rollup merge of #155347 - balt-dev:patch-1, r=cuviper
matthiaskrgr Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ 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)
- [`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)
- [`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::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)


These previously stable APIs are now stable in const contexts:
Expand Down
36 changes: 12 additions & 24 deletions compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,25 +140,19 @@ impl<T> TypedArena<T> {
/// Allocates an object in the `TypedArena`, returning a reference to it.
#[inline]
pub fn alloc(&self, object: T) -> &mut T {
assert!(size_of::<T>() != 0);

if self.ptr == self.end {
self.grow(1)
}

unsafe {
if size_of::<T>() == 0 {
self.ptr.set(self.ptr.get().wrapping_byte_add(1));
let ptr = ptr::NonNull::<T>::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
}
}

Expand Down Expand Up @@ -302,16 +296,10 @@ impl<T> TypedArena<T> {
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::<T>() == 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::<T>()
};
assert_ne!(size_of::<T>(), 0);
// FIXME: this should *likely* use `offset_from`, but more
// investigation is needed (including running tests in miri).
let diff = (end - start) / size_of::<T>();
// Pass that to the `destroy` method.
unsafe {
last_chunk.destroy(diff);
Expand Down
18 changes: 3 additions & 15 deletions compiler/rustc_arena/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ impl<T> TypedArena<T> {
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);
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -207,7 +194,8 @@ thread_local! {
static DROP_COUNTER: Cell<u32> = Cell::new(0)
}

struct SmallDroppable;
#[allow(unused)]
struct SmallDroppable(u8);

impl Drop for SmallDroppable {
fn drop(&mut self) {
Expand All @@ -222,7 +210,7 @@ fn test_typed_arena_drop_small_count() {
let arena: TypedArena<SmallDroppable> = 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
};
Expand Down
56 changes: 46 additions & 10 deletions compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -218,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",
Expand All @@ -230,7 +230,13 @@ 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();
} else {
writeln!(begin, ".text").unwrap();
}
writeln!(begin, ".balign {align_bytes}").unwrap();
write_linkage(&mut begin).unwrap();
match visibility {
Expand All @@ -249,14 +255,20 @@ 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. 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();
}
writeln!(begin, ".balign {align_bytes}").unwrap();
write_linkage(&mut begin).unwrap();
match visibility {
Expand All @@ -267,7 +279,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();
}
Expand All @@ -278,8 +292,30 @@ 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, ".section {section},\"xr\"").unwrap()
} else if !function_sections {
// 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
// sections with the same name and comdat. It adds `unique,<id>` 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();
writeln!(begin, "{asm_name}:").unwrap();
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5559,15 +5559,16 @@ 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.
/// #[cfg(false)]
/// fn foo(...) {
///
/// }
/// ```
#[doc = "```"]
///
/// {{produces}}
///
Expand All @@ -5591,11 +5592,11 @@ 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,
};
}

Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,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.
Expand Down
10 changes: 10 additions & 0 deletions src/tools/run-make-support/src/external_deps/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
Loading
Loading