Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d218e7f
`std::any::TypeId`: remove misplaced "and" in `Unique<T>` example
DanielEScherzer Mar 6, 2026
4e75261
Add Sized supertrait for CoerceUnsized and DispatchFromDyn
Darksonn Apr 7, 2026
2d8ae32
Add a test for the ICE
Darksonn Apr 7, 2026
46a84f6
Add run-pass test for dyn Receiver
Darksonn Apr 7, 2026
80bb813
Inline `field_match_pairs` into its callers
Zalathar Apr 11, 2026
4a5c24f
Move the recursive step out of `prefix_slice_suffix`
Zalathar Apr 11, 2026
b17a3e2
Fix misleading "borrowed data escapes outside of function" diagnostic
lapla-cogito Apr 14, 2026
0e522d6
naked functions: respect `function_sections` on windows
folkertdev Oct 17, 2025
872301b
naked functions: respect `function_sections` on linux/macos
folkertdev Oct 17, 2025
25e1647
naked functions: add run-make test for DCE
folkertdev Oct 17, 2025
bc4aad3
naked-functions: properly document the -Zfunction-sections windows st…
folkertdev Jan 17, 2026
7787bd9
fix macho section specifier & windows test
folkertdev Mar 29, 2026
cc1ebb5
add uefi to windows link section test
folkertdev Apr 16, 2026
41afd5f
handle `uefi` and test assembly versus regular functions
folkertdev Apr 16, 2026
a66b781
`impl Default for RepeatN`
cuviper Apr 11, 2025
2db9de3
add `ignore-cross-compile` to run-make test
folkertdev Apr 16, 2026
9b36d40
ptr: update text in intro text to one in with_addr doc
tshepang Apr 17, 2026
b967de6
rustdoc: fix issues with redundant_explicit_links
tonywu6 Apr 17, 2026
d9c7177
remove unnecessary safety conditions related to unchecked uint arithm…
hxuhack Apr 17, 2026
10cc6c4
docs: Fix typo in std/src/thread/scoped.rs
MadeInShineA Apr 17, 2026
6525e06
`std::error::Request`: add missing period in docs
DanielEScherzer Apr 17, 2026
1d1aa9a
`std::error::Request`: more documentation cleanup
DanielEScherzer Apr 17, 2026
a779e05
Fix ICE in borrowck mutability suggestion with multi-byte ref sigil
lapla-cogito Apr 17, 2026
baf4388
Rollup merge of #147811 - folkertdev:naked-function-sections, r=Amanieu
jhpratt Apr 18, 2026
db3d084
Rollup merge of #154935 - Darksonn:dyn-trait-dyn-compat, r=scottmcm
jhpratt Apr 18, 2026
221dab8
Rollup merge of #139690 - cuviper:iter_repeat_n_default, r=tgross35
jhpratt Apr 18, 2026
354bfa4
Rollup merge of #153511 - DanielEScherzer:patch-3, r=scottmcm
jhpratt Apr 18, 2026
eb18553
Rollup merge of #154943 - Zalathar:for-each-subpat, r=Nadrieril
jhpratt Apr 18, 2026
eb52efb
Rollup merge of #155295 - lapla-cogito:issue_154350, r=JohnTitor
jhpratt Apr 18, 2026
8b07a03
Rollup merge of #155427 - tshepang:tshepang/match-text-in-with_addr, …
jhpratt Apr 18, 2026
e3676b5
Rollup merge of #155428 - lapla-cogito:issue_139089, r=mejrs
jhpratt Apr 18, 2026
afb3f3d
Rollup merge of #155435 - tonywu6:main, r=lolbinarycat
jhpratt Apr 18, 2026
0c326ec
Rollup merge of #155450 - safer-rust:fix-doc2, r=jhpratt
jhpratt Apr 18, 2026
4fa293c
Rollup merge of #155454 - MadeInShineA:issue-155275-fix, r=lqd
jhpratt Apr 18, 2026
0bfd952
Rollup merge of #155467 - DanielEScherzer:patch-2, r=mejrs
jhpratt Apr 18, 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
17 changes: 14 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,9 +1410,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
(span, " mut".to_owned(), true)
// If there is already a binding, we modify it to be `mut`.
} else if binding_exists {
// Shrink the span to just after the `&` in `&variable`.
let span = span.with_lo(span.lo() + BytePos(1)).shrink_to_lo();
(span, "mut ".to_owned(), true)
// Replace the sigil with the mutable version. We may be dealing
// with parser recovery here and cannot assume the user actually
// typed `&` or `*const`, so we compute the prefix from the snippet.
let Ok(src) = self.infcx.tcx.sess.source_map().span_to_snippet(span) else {
return;
};
let (prefix_len, replacement) = if local_decl.ty.is_ref() {
(src.chars().next().map_or(0, char::len_utf8), "&mut ")
} else {
(src.find("const").map_or(1, |i| i + "const".len()), "*mut ")
};
let ws_len = src[prefix_len..].len() - src[prefix_len..].trim_start().len();
let span = span.with_hi(span.lo() + BytePos((prefix_len + ws_len) as u32));
(span, replacement.to_owned(), true)
} else {
// Otherwise, suggest that the user annotates the binding; We provide the
// type of the local.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|| (*category == ConstraintCategory::Assignment
&& self.regioncx.universal_regions().defining_ty.is_fn_def())
|| self.regioncx.universal_regions().defining_ty.is_const()
|| (fr_name_and_span.is_none()
&& self.regioncx.universal_regions().defining_ty.is_fn_def())
{
return self.report_general_error(errci);
}
Expand Down
64 changes: 54 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, Os};

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,22 @@ 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();
} else {
writeln!(begin, ".section __TEXT,__text,regular,pure_instructions").unwrap();
}
writeln!(begin, ".balign {align_bytes}").unwrap();
write_linkage(&mut begin).unwrap();
match visibility {
Expand All @@ -267,7 +281,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 +294,36 @@ 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();
}
Env::Unspecified => match &tcx.sess.target.options.os {
Os::Uefi => {
writeln!(begin, ".section .text,\"xr\",one_only,{asm_name}").unwrap();
}
_ => bug!("unexpected coff target {}", tcx.sess.target.llvm_target),
},
other => bug!("unexpected coff env {other:?}"),
}
}
write_linkage(&mut begin).unwrap();
writeln!(begin, ".balign {align_bytes}").unwrap();
writeln!(begin, "{asm_name}:").unwrap();
Expand Down
151 changes: 65 additions & 86 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,77 +12,58 @@ use crate::builder::matches::{
FlatPat, MatchPairTree, PatConstKind, PatternExtraData, SliceLenOp, TestableCase,
};

impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Builds and pushes [`MatchPairTree`] subtrees, one for each pattern in
/// `subpatterns`, representing the fields of a [`PatKind::Variant`] or
/// [`PatKind::Leaf`].
///
/// Used internally by [`MatchPairTree::for_pattern`].
fn field_match_pairs(
&mut self,
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
extra_data: &mut PatternExtraData<'tcx>,
place: PlaceBuilder<'tcx>,
subpatterns: &[FieldPat<'tcx>],
) {
for fieldpat in subpatterns {
let place = place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
MatchPairTree::for_pattern(place, &fieldpat.pattern, self, match_pairs, extra_data);
}
/// For an array or slice pattern's subpatterns (prefix/slice/suffix), returns a list
/// of those subpatterns, each paired with a suitably-projected [`PlaceBuilder`].
fn prefix_slice_suffix<'a, 'tcx>(
place: &PlaceBuilder<'tcx>,
array_len: Option<u64>, // Some for array patterns; None for slice patterns
prefix: &'a [Pat<'tcx>],
opt_slice: &'a Option<Box<Pat<'tcx>>>,
suffix: &'a [Pat<'tcx>],
) -> Vec<(PlaceBuilder<'tcx>, &'a Pat<'tcx>)> {
let prefix_len = u64::try_from(prefix.len()).unwrap();
let suffix_len = u64::try_from(suffix.len()).unwrap();

let mut output_pairs =
Vec::with_capacity(prefix.len() + usize::from(opt_slice.is_some()) + suffix.len());

// For slice patterns with a `..` followed by 0 or more suffix subpatterns,
// the actual slice index of those subpatterns isn't statically known, so
// we have to index them relative to the end of the slice.
//
// For array patterns, all subpatterns are indexed relative to the start.
let (min_length, is_array) = match array_len {
Some(len) => (len, true),
None => (prefix_len + suffix_len, false),
};

for (offset, prefix_subpat) in (0u64..).zip(prefix) {
let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
let subplace = place.clone_project(elem);
output_pairs.push((subplace, prefix_subpat));
}

/// Builds [`MatchPairTree`] subtrees for the prefix/middle/suffix parts of an
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
///
/// Used internally by [`MatchPairTree::for_pattern`].
fn prefix_slice_suffix(
&mut self,
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
extra_data: &mut PatternExtraData<'tcx>,
place: &PlaceBuilder<'tcx>,
array_len: Option<u64>,
prefix: &[Pat<'tcx>],
opt_slice: &Option<Box<Pat<'tcx>>>,
suffix: &[Pat<'tcx>],
) {
let prefix_len = u64::try_from(prefix.len()).unwrap();
let suffix_len = u64::try_from(suffix.len()).unwrap();

// For slice patterns with a `..` followed by 0 or more suffix subpatterns,
// the actual slice index of those subpatterns isn't statically known, so
// we have to index them relative to the end of the slice.
//
// For array patterns, all subpatterns are indexed relative to the start.
let (min_length, is_array) = match array_len {
Some(len) => (len, true),
None => (prefix_len + suffix_len, false),
if let Some(slice_subpat) = opt_slice {
let elem = PlaceElem::Subslice {
from: prefix_len,
to: if is_array { min_length - suffix_len } else { suffix_len },
from_end: !is_array,
};
let subplace = place.clone_project(elem);
output_pairs.push((subplace, slice_subpat));
}

for (offset, subpattern) in (0u64..).zip(prefix) {
let elem = ProjectionElem::ConstantIndex { offset, min_length, from_end: false };
let place = place.clone_project(elem);
MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
}

if let Some(subslice_pat) = opt_slice {
let subslice = place.clone_project(PlaceElem::Subslice {
from: prefix_len,
to: if is_array { min_length - suffix_len } else { suffix_len },
from_end: !is_array,
});
MatchPairTree::for_pattern(subslice, subslice_pat, self, match_pairs, extra_data);
}

for (end_offset, subpattern) in (1u64..).zip(suffix.iter().rev()) {
let elem = ProjectionElem::ConstantIndex {
offset: if is_array { min_length - end_offset } else { end_offset },
min_length,
from_end: !is_array,
};
let place = place.clone_project(elem);
MatchPairTree::for_pattern(place, subpattern, self, match_pairs, extra_data)
}
for (offset_from_end, suffix_subpat) in (1u64..).zip(suffix.iter().rev()) {
let elem = ProjectionElem::ConstantIndex {
offset: if is_array { min_length - offset_from_end } else { offset_from_end },
min_length,
from_end: !is_array,
};
let subplace = place.clone_project(elem);
output_pairs.push((subplace, suffix_subpat));
}

output_pairs
}

impl<'tcx> MatchPairTree<'tcx> {
Expand Down Expand Up @@ -239,15 +220,11 @@ impl<'tcx> MatchPairTree<'tcx> {
_ => None,
};
if let Some(array_len) = array_len {
cx.prefix_slice_suffix(
&mut subpairs,
extra_data,
&place_builder,
Some(array_len),
prefix,
slice,
suffix,
);
for (subplace, subpat) in
prefix_slice_suffix(&place_builder, Some(array_len), prefix, slice, suffix)
{
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
}
} else {
// If the array length couldn't be determined, ignore the
// subpatterns and delayed-assert that compilation will fail.
Expand All @@ -263,15 +240,11 @@ impl<'tcx> MatchPairTree<'tcx> {
None
}
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
cx.prefix_slice_suffix(
&mut subpairs,
extra_data,
&place_builder,
None,
prefix,
slice,
suffix,
);
for (subplace, subpat) in
prefix_slice_suffix(&place_builder, None, prefix, slice, suffix)
{
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
}

if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
// This pattern is shaped like `[..]`. It can match a slice
Expand All @@ -294,7 +267,10 @@ impl<'tcx> MatchPairTree<'tcx> {

PatKind::Variant { adt_def, variant_index, args: _, ref subpatterns } => {
let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)`
cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns);
for &FieldPat { field, pattern: ref subpat } in subpatterns {
let subplace = downcast_place.clone_project(PlaceElem::Field(field, subpat.ty));
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
}

// We treat non-exhaustive enums the same independent of the crate they are
// defined in, to avoid differences in the operational semantics between crates.
Expand All @@ -308,7 +284,10 @@ impl<'tcx> MatchPairTree<'tcx> {
}

PatKind::Leaf { ref subpatterns } => {
cx.field_match_pairs(&mut subpairs, extra_data, place_builder, subpatterns);
for &FieldPat { field, pattern: ref subpat } in subpatterns {
let subplace = place_builder.clone_project(PlaceElem::Field(field, subpat.ty));
MatchPairTree::for_pattern(subplace, subpat, cx, &mut subpairs, extra_data);
}
None
}

Expand Down
2 changes: 1 addition & 1 deletion library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ impl dyn Any + Send + Sync {
///
/// The following is an example program that tries to use `TypeId::of` to
/// implement a generic type `Unique<T>` that guarantees unique instances for each `Unique<T>`,
/// that is, and for each type `T` there can be at most one value of type `Unique<T>` at any time.
/// that is, for each type `T` there can be at most one value of type `Unique<T>` at any time.
///
/// ```
/// mod unique {
Expand Down
18 changes: 9 additions & 9 deletions library/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,37 +494,37 @@ where
/// `Request` supports generic, type-driven access to data. Its use is currently restricted to the
/// standard library in cases where trait authors wish to allow trait implementors to share generic
/// information across trait boundaries. The motivating and prototypical use case is
/// `core::error::Error` which would otherwise require a method per concrete type (eg.
/// `core::error::Error` which would otherwise require a method per concrete type (e.g.
/// `std::backtrace::Backtrace` instance that implementors want to expose to users).
///
/// # Data flow
///
/// To describe the intended data flow for Request objects, let's consider two conceptual users
/// separated by API boundaries:
///
/// * Consumer - the consumer requests objects using a Request instance; eg a crate that offers
/// * Consumer - the consumer requests objects using a Request instance; e.g. a crate that offers
/// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`.
///
/// * Producer - the producer provides objects when requested via Request; eg. a library with an
/// * Producer - the producer provides objects when requested via Request; e.g. a library with an
/// an `Error` implementation that automatically captures backtraces at the time instances are
/// created.
///
/// The consumer only needs to know where to submit their request and are expected to handle the
/// The consumer only needs to know where to submit their request and is expected to handle the
/// request not being fulfilled by the use of `Option<T>` in the responses offered by the producer.
///
/// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise
/// prepared to generate a value requested). eg, `backtrace::Backtrace` or
/// `std::backtrace::Backtrace`
/// prepared to generate a value requested). e.g., `backtrace::Backtrace` or
/// `std::backtrace::Backtrace`.
/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the
/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and
/// `request_value` to simplify obtaining an `Option<T>` for a given type.
/// * The Producer, when requested, populates the given Request object which is given as a mutable
/// reference.
/// * The Consumer extracts a value or reference to the requested type from the `Request` object
/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and `
/// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at
/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and
/// `request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at
/// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the
/// Producer cannot currently offer an instance of the requested type, not it can't or never will.
/// Producer cannot currently offer an instance of the requested type, not that it can't or never will.
///
/// # Examples
///
Expand Down
Loading
Loading