Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
314a75b
`TrivialTypeTraversalImpls!`: also impl `GenericTypeVisitable`
ada4a Sep 16, 2026
e394051
dogfood: add missing `GenericTypeVisitable` impls
ada4a Sep 30, 2026
bc6cee4
Tweak `WellFormedLoc`
estebank Oct 7, 2026
9083df3
Add tests for 84346 and 105753
estebank Oct 7, 2026
55d1925
Silence redundant failed obligations on the same statement
estebank Oct 7, 2026
9d0888f
Use `WellFormedLoc::HirId` for `offset_of!` `Sized` obligation cause …
estebank Oct 7, 2026
df42c7b
elide potentially-problematic projection clauses
dianne Oct 6, 2026
3e2bec1
Fix COFF renaming of decorated (stdcall/fastcall/vectorcall) exports
cezarbbb Sep 29, 2026
19735e0
add MISSING_GENERIC_TYPE_VISITABLE lint
ada4a Aug 1, 2026
7cbe17e
Condense AdtDef lang item checks into one match
oli-obk Oct 8, 2026
02f6b38
_Complex for mips
folkertdev Jul 26, 2026
e5ddf33
Add `bf16` to arm features
Jamesbarford Oct 8, 2026
8186e2c
Include enclosing item's context on const errors
estebank Oct 8, 2026
71b73c0
Rollup merge of #163462 - cezarbbb:symbol-edit-undecorate-coff, r=bjorn3
JonathanBrouwer Oct 8, 2026
0dd1861
Rollup merge of #163855 - estebank:const-context-spans, r=oli-obk
JonathanBrouwer Oct 8, 2026
77d7f83
Rollup merge of #163913 - estebank:wellformedloc, r=oli-obk
JonathanBrouwer Oct 8, 2026
050f75a
Rollup merge of #163538 - ada4a:missing-generic-type-visitable, r=Jon…
JonathanBrouwer Oct 8, 2026
1f3a582
Rollup merge of #163617 - folkertdev:complex-mips, r=beetrees
JonathanBrouwer Oct 8, 2026
417981c
Rollup merge of #163958 - dianne:fix-rustaceansareawesome-take-2-part…
JonathanBrouwer Oct 8, 2026
405d154
Rollup merge of #163974 - oli-obk:push-psmmpmqzwvmo, r=lqd
JonathanBrouwer Oct 8, 2026
5636514
Rollup merge of #163979 - Jamesbarford:feat/add-bf16-to-arm-features,…
JonathanBrouwer Oct 8, 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
52 changes: 6 additions & 46 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use rustc_span::{Symbol, bug};
use rustc_structures::{CrateType, NativeLibKind};
use rustc_target::spec::crt_objects::CrtObjects;
use rustc_target::spec::{
Arch, BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents,
BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents,
LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, Os, RelocModel,
RelroLevel, SanitizerSet, SplitDebuginfo,
};
Expand All @@ -58,7 +58,7 @@ use super::linker::{self, Linker};
use super::metadata::{MetadataPosition, create_wrapper_file};
use super::rmeta_link::RmetaLinkCache;
use super::rpath::{self, RPathConfig};
use super::{apple, rmeta_link, versioned_llvm_target};
use super::{apple, rmeta_link, symbol_export, versioned_llvm_target};
use crate::base::needs_allocator_shim_for_linking;
use crate::{
CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, SymbolExport,
Expand Down Expand Up @@ -2759,10 +2759,6 @@ fn add_rpath_args(
}
}

fn strip_numeric_suffix<'a>(base: &'a str, suffix: impl AsRef<str>, fallback: &'a str) -> &'a str {
if suffix.as_ref().parse::<u32>().is_ok() { base } else { fallback }
}

fn undecorate_c_symbol<'a>(
name: &'a str,
sess: &Session,
Expand All @@ -2775,47 +2771,11 @@ fn undecorate_c_symbol<'a>(
name.strip_prefix('_')
}
BinaryFormat::Coff => {
// MSVC C++ mangled names start with '?' and use a completely different
// decorating scheme that includes '@@' as structural delimiters.
// They must not be subjected to C calling-convention undecoration.
if name.starts_with('?') {
return Some(name);
// COFF undecoration is shared with `symbol_edit`'s binary-level matching.
match symbol_export::coff_machine_for_arch(&sess.target.arch) {
Some(machine) => Some(symbol_export::undecorate_coff_symbol(name, machine, kind)),
None => Some(name),
}
Some(match sess.target.arch {
Arch::X86 => {
// COFF 32-bit: strip calling-convention decorations.
if let Some(rest) = name.strip_prefix('@') {
// fastcall: @foo@N -> foo
rest.rsplit_once('@')
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
} else if let Some(stripped) = name.strip_prefix('_') {
if let Some((base, suffix)) = stripped.rsplit_once('@') {
// stdcall: _foo@N -> foo
strip_numeric_suffix(base, suffix, stripped)
} else {
// cdecl: _foo -> foo
stripped
}
} else {
// vectorcall: foo@@N -> foo
name.rsplit_once("@@")
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
}
}
Arch::X86_64 => {
// COFF 64-bit: vectorcall mangling (foo@@N -> foo) also applies on x86_64.
name.rsplit_once("@@")
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
}
Arch::Arm64EC if kind == SymbolExportKind::Text => {
// Arm64EC: `#` prefix distinguishes ARM64EC text symbols from x64 thunks.
name.strip_prefix('#').unwrap_or(name)
}
_ => name,
})
}
// ELF: no decoration
_ => Some(name),
Expand Down
67 changes: 22 additions & 45 deletions compiler/rustc_codegen_ssa/src/back/symbol_edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use object::read::elf::{SectionHeader as _, Sym as _};
use object::read::macho::Nlist;
use object::{Endianness, elf, macho, pe};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::middle::exported_symbols::SymbolExportKind;

use super::symbol_export::undecorate_coff_symbol;

struct Patch {
offset: usize,
Expand Down Expand Up @@ -58,20 +61,8 @@ pub(super) fn apply_edits<'a>(
rename,
mem::offset_of!(macho::Nlist32<Endianness>, n_type),
),
Some(object::File::Coff(f)) => coff_edit_impl(
data,
f.coff_header(),
hide,
rename,
coff_strip_underscore(f.coff_header()),
),
Some(object::File::CoffBig(f)) => coff_edit_impl(
data,
f.coff_header(),
hide,
rename,
coff_strip_underscore(f.coff_header()),
),
Some(object::File::Coff(f)) => coff_edit_impl(data, f.coff_header(), hide, rename),
Some(object::File::CoffBig(f)) => coff_edit_impl(data, f.coff_header(), hide, rename),
_ => None,
};
match result {
Expand Down Expand Up @@ -99,28 +90,20 @@ pub(super) fn collect_internal_names(
object::File::MachO32(_) => {
macho_collect_impl::<macho::MachHeader32<Endianness>>(data, exported, out)
}
object::File::Coff(f) => coff_collect_impl(
data,
f.coff_header(),
exported,
out,
coff_strip_underscore(f.coff_header()),
),
object::File::CoffBig(f) => coff_collect_impl(
data,
f.coff_header(),
exported,
out,
coff_strip_underscore(f.coff_header()),
),
object::File::Coff(f) => coff_collect_impl(data, f.coff_header(), exported, out),
object::File::CoffBig(f) => coff_collect_impl(data, f.coff_header(), exported, out),
_ => {}
}
}

/// Whether this machine's COFF ABI decorates external symbols with a leading `_`
/// (i686 only).
fn coff_strip_underscore(header: &impl CoffHeader) -> bool {
header.machine() == pe::IMAGE_FILE_MACHINE_I386
/// The `SymbolExportKind` of a COFF symbol, so `#`-prefixed `Arm64EC` text symbols are told
/// apart from data symbols during undecoration.
fn coff_symbol_kind(sym: &impl object::read::coff::ImageSymbol) -> SymbolExportKind {
if sym.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION {
SymbolExportKind::Text
} else {
SymbolExportKind::Data
}
}

fn elf_collect_impl<Elf: object::read::elf::FileHeader<Endian = Endianness>>(
Expand Down Expand Up @@ -485,10 +468,10 @@ fn coff_collect_impl<'data, Coff: CoffHeader>(
header: &'data Coff,
exported: &FxHashSet<String>,
out: &mut FxHashSet<String>,
strip_underscore: bool,
) {
let Ok(symbols) = header.symbols(data) else { return };
let strings = symbols.strings();
let machine = header.machine();

for (_index, sym) in symbols.iter() {
let sclass = sym.storage_class();
Expand All @@ -499,15 +482,10 @@ fn coff_collect_impl<'data, Coff: CoffHeader>(
continue;
}
let Ok(name_bytes) = sym.name(strings) else { continue };
let Ok(mut name) = str::from_utf8(name_bytes).map(String::from) else { continue };
if strip_underscore {
name = name.strip_prefix('_').unwrap_or(&name).to_string();
}
let is_exported = exported.contains(&name)
|| (header.machine() == pe::IMAGE_FILE_MACHINE_ARM64EC
&& name.strip_prefix('#').is_some_and(|name| exported.contains(name)));
if !is_exported {
out.insert(name);
let Ok(name) = str::from_utf8(name_bytes) else { continue };
let name = undecorate_coff_symbol(name, machine, coff_symbol_kind(sym));
if !exported.contains(name) {
out.insert(name.to_string());
}
}
}
Expand All @@ -517,7 +495,6 @@ fn coff_edit_impl<'data, Coff: CoffHeader>(
header: &'data Coff,
hide: bool,
rename: Option<&(FxHashSet<String>, &str)>,
strip_underscore: bool,
) -> Option<Vec<u8>> {
// COFF has no visibility concept, so hiding is unsupported; the caller
// has already warned and does not request it.
Expand Down Expand Up @@ -545,6 +522,7 @@ fn coff_edit_impl<'data, Coff: CoffHeader>(

let Ok(symbols) = header.symbols(data) else { return None };
let strings = symbols.strings();
let machine = header.machine();

let mut renames = Vec::new();
for (index, sym) in symbols.iter() {
Expand All @@ -554,8 +532,7 @@ fn coff_edit_impl<'data, Coff: CoffHeader>(
}
let Ok(name_bytes) = sym.name(strings) else { continue };
let Ok(name) = str::from_utf8(name_bytes) else { continue };
let check_name =
if strip_underscore { name.strip_prefix('_').unwrap_or(name) } else { name };
let check_name = undecorate_coff_symbol(name, machine, coff_symbol_kind(sym));
if rename.is_some_and(|(rename_set, _)| rename_set.contains(check_name)) {
renames.push(RenameEntry {
name_field_offset: symbol_bytes_offset + index.0 * sym_size,
Expand Down
63 changes: 63 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::hash_map::Entry::*;

use object::pe;
use rustc_abi::{CanonAbi, X86Call};
use rustc_ast::expand::allocator::{AllocatorKind, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
use rustc_crate_store::CrateDepKind;
Expand Down Expand Up @@ -813,6 +814,68 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
maybe_emutls_symbol_name(tcx, symbol, &undecorated).unwrap_or(undecorated)
}

fn strip_numeric_suffix<'a>(base: &'a str, suffix: impl AsRef<str>, fallback: &'a str) -> &'a str {
if suffix.as_ref().parse::<u32>().is_ok() { base } else { fallback }
}

/// COFF `IMAGE_FILE_MACHINE_*` for an arch with decorated symbols, or `None`.
pub(super) fn coff_machine_for_arch(arch: &Arch) -> Option<u16> {
match *arch {
Arch::X86 => Some(pe::IMAGE_FILE_MACHINE_I386),
Arch::X86_64 => Some(pe::IMAGE_FILE_MACHINE_AMD64),
Arch::Arm64EC => Some(pe::IMAGE_FILE_MACHINE_ARM64EC),
_ => None,
}
}

/// Undecorated counterpart of [`linking_symbol_name_for_instance_in_crate`].
pub(super) fn undecorate_coff_symbol<'a>(
name: &'a str,
machine: u16,
kind: SymbolExportKind,
) -> &'a str {
// MSVC C++ mangled names start with '?' and use a completely different
// decorating scheme that includes '@@' as structural delimiters.
// They must not be subjected to C calling-convention undecoration.
if name.starts_with('?') {
return name;
}
match machine {
pe::IMAGE_FILE_MACHINE_I386 => {
if let Some(rest) = name.strip_prefix('@') {
// fastcall: @foo@N -> foo
rest.rsplit_once('@')
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
} else if let Some(stripped) = name.strip_prefix('_') {
if let Some((base, suffix)) = stripped.rsplit_once('@') {
// stdcall: _foo@N -> foo
strip_numeric_suffix(base, suffix, stripped)
} else {
// cdecl: _foo -> foo
stripped
}
} else {
// vectorcall: foo@@N -> foo
name.rsplit_once("@@")
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
}
}
pe::IMAGE_FILE_MACHINE_AMD64 => {
// vectorcall: foo@@N -> foo
name.rsplit_once("@@")
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
}
pe::IMAGE_FILE_MACHINE_ARM64EC if kind == SymbolExportKind::Text => {
// `#` prefix distinguishes ARM64EC text symbols from x64 thunks.
name.strip_prefix('#').unwrap_or(name)
}
_ => name,
}
}

/// On amdhsa, `gpu-kernel` functions have an associated metadata object with a `.kd` suffix.
/// Add it to the symbols list for all kernel functions, so that it is exported in the linked
/// object.
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ fn report_eval_error<'tcx>(
where_ = if num_frames == 0 { "here" } else { "inside this call" },
),
);
for span in crate::util::context_spans(*ecx.tcx, span, cid.instance.def_id()) {
diag.span_context(span);
}
for frame in frames {
diag.subdiagnostic(frame);
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_const_eval/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ pub(crate) struct NonConstImplNote {
#[derive(Clone)]
pub(crate) struct FrameNote {
pub span: Span,
pub span_context: Vec<Span>,
pub times: i32,
pub where_: &'static str,
pub instance: String,
Expand All @@ -322,6 +323,9 @@ impl Subdiagnostic for FrameNote {
if self.has_label && !self.span.is_dummy() {
span.push_span_label(self.span, msg!("the failure occurred here"));
}
for sp in &self.span_context {
span.push_span_context(*sp);
}
let msg = msg!(
r#"{$times ->
[0] inside {$where_ ->
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_const_eval/src/interpret/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,21 @@ impl<'tcx> FrameInfo<'tcx> {
diagnostics::FrameNote {
where_: "closure",
span,
span_context: vec![],
instance: String::new(),
times: 0,
has_label: false,
}
} else {
let instance = format!("{}", self.instance);
let span_context = crate::util::context_spans(tcx, span, self.instance.def_id());
// Note: this triggers a `must_produce_diag` state, which means that if we ever get
// here we must emit a diagnostic. We should never display a `FrameInfo` unless we
// actually want to emit a warning or error to the user.
diagnostics::FrameNote {
where_: "instance",
span,
span_context,
instance,
times: 0,
has_label: false,
Expand Down
Loading
Loading