Skip to content

Rollup of 15 pull requests #144382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 43 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
41e6f76
future-incompat lints: don't link to the nightly edition-guide version
dianne Jul 16, 2025
ac87434
Implement support for explicit tail calls in the MIR block builders a…
xacrimon Jul 20, 2025
a96bd57
chore: clang-format
xacrimon Jul 20, 2025
205f4ca
tests: add ui fail/pass tests and llvm ir tail codegen tests
xacrimon Jul 21, 2025
3fac279
chore: fix typo
xacrimon Jul 21, 2025
55b5612
don't end lifetimes after call
xacrimon Jul 21, 2025
2cd84dc
recursion-no-tce.rs should be run-crash
xacrimon Jul 21, 2025
d424207
fix typo in codegen test
xacrimon Jul 21, 2025
dad96b1
Use serde for target spec json deserialize
Noratrieb Jul 20, 2025
e5a5062
add an error message if you attempt to pass indirect args via guarant…
xacrimon Jul 21, 2025
ecf34e1
use span_bug instead of bug
xacrimon Jul 21, 2025
c4eb077
Ensure we codegen and don't internalize the entrypoint
saethlin Jul 17, 2025
6e8762f
Use less HIR in check_private_in_public.
cjgillot Oct 1, 2023
0aa6170
Add a test case for ui test false-sealed-traits-note.rs
yuk1ty Jul 21, 2025
9e75032
rustdoc: avoid allocating a temp String for aliases in search index
lolbinarycat Jul 22, 2025
3440bc9
Unquerify extern_mod_stmt_cnum.
cjgillot Jul 3, 2025
95de0aa
rustc_resolve: get rid of unused rustdoc::span_of_fragments_with_expa…
lolbinarycat Jul 22, 2025
ab8e521
get rid of some false negatives in rustdoc::broken_intra_doc_links
lolbinarycat Nov 7, 2024
91b9b33
adjust more unit tests to reflect more aggressive intra-doc linting
lolbinarycat Nov 8, 2024
de68c59
rustdoc::broken_intra_doc_links: no backticks = use old behavior
lolbinarycat Apr 18, 2025
c5b39cf
rustdoc: update tests to match new lint behavior
lolbinarycat Apr 18, 2025
82df892
rustdoc::broken_intra_doc_links: only be lenient with shortcut links
lolbinarycat Apr 19, 2025
2d38996
move bad-intra-doc test into intra-doc dir
lolbinarycat Apr 19, 2025
9bb9c39
Don't suggest assoc ty bound on non-angle-bracketed problematic assoc…
fmease Jul 22, 2025
eb9c654
std: net: uefi: Add support to query connection data
Ayush1325 Jul 12, 2025
af06bb9
Stop using the old `validate_attr` logic for stability attributes
JonathanBrouwer Jul 23, 2025
37480bc
coretests/num: use ldexp instead of hard-coding a power of 2
RalfJung Jul 21, 2025
371b010
generate elf symbol version in raw-dylib
usamoi Jul 20, 2025
cc8d2a4
Rollup merge of #132748 - lolbinarycat:rustdoc-intra-doc-link-warn-mo…
fmease Jul 23, 2025
8469ec1
Rollup merge of #143374 - cjgillot:bare-extern-crate-map, r=petrochenkov
fmease Jul 23, 2025
b3e5b41
Rollup merge of #143838 - Ayush1325:uefi-tcp4-config-data, r=tgross35
fmease Jul 23, 2025
031ac3b
Rollup merge of #144014 - dianne:edition-guide-links, r=estebank
fmease Jul 23, 2025
b8a303d
Rollup merge of #144094 - saethlin:codegen-the-main-fn, r=petrochenkov
fmease Jul 23, 2025
51c2923
Rollup merge of #144218 - Noratrieb:target-spec-json-de-jank, r=fee1-…
fmease Jul 23, 2025
477c1ee
Rollup merge of #144221 - usamoi:versym, r=bjorn3
fmease Jul 23, 2025
cee3373
Rollup merge of #144232 - xacrimon:explicit-tail-call, r=oli-obk
fmease Jul 23, 2025
be4a727
Rollup merge of #144240 - yuk1ty:false-sealed-traits-note-reported-in…
fmease Jul 23, 2025
c39a432
Rollup merge of #144247 - RalfJung:ldexp, r=tgross35
fmease Jul 23, 2025
6ae4bbc
Rollup merge of #144276 - cjgillot:no-hir-privacy, r=petrochenkov
fmease Jul 23, 2025
a9e2fb2
Rollup merge of #144320 - lolbinarycat:rustdoc-search_index-BTreeMap-…
fmease Jul 23, 2025
9b1b0b1
Rollup merge of #144334 - lolbinarycat:rustdoc-span_of_fragments-reve…
fmease Jul 23, 2025
a49d9b9
Rollup merge of #144335 - fmease:no-angle-no-colon, r=SparrowLii
fmease Jul 23, 2025
1701ab5
Rollup merge of #144358 - JonathanBrouwer:fix-stability-malformed, r=…
fmease Jul 23, 2025
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
13 changes: 13 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4563,7 +4563,10 @@ dependencies = [
"rustc_macros",
"rustc_serialize",
"rustc_span",
"serde",
"serde_derive",
"serde_json",
"serde_path_to_error",
"tracing",
]

Expand Down Expand Up @@ -4955,6 +4958,16 @@ dependencies = [
"serde",
]

[[package]]
name = "serde_path_to_error"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
dependencies = [
"itoa",
"serde",
]

[[package]]
name = "serde_spanned"
version = "0.6.9"
Expand Down
26 changes: 22 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,15 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
template!(NameValueStr: "deprecation message"),
|this, cx, args| {
reject_outside_std!(cx);
this.allowed_through_unstable_modules =
args.name_value().and_then(|i| i.value_as_str())
let Some(nv) = args.name_value() else {
cx.expected_name_value(cx.attr_span, None);
return;
};
let Some(value_str) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return;
};
this.allowed_through_unstable_modules = Some(value_str);
},
),
];
Expand Down Expand Up @@ -247,7 +254,12 @@ pub(crate) fn parse_stability<S: Stage>(
let mut feature = None;
let mut since = None;

for param in args.list()?.mixed() {
let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span);
return None;
};

for param in list.mixed() {
let param_span = param.span();
let Some(param) = param.meta_item() else {
cx.emit_err(session_diagnostics::UnsupportedLiteral {
Expand Down Expand Up @@ -322,7 +334,13 @@ pub(crate) fn parse_unstability<S: Stage>(
let mut is_soft = false;
let mut implied_by = None;
let mut old_name = None;
for param in args.list()?.mixed() {

let ArgParser::List(list) = args else {
cx.expected_list(cx.attr_span);
return None;
};

for param in list.mixed() {
let Some(param) = param.meta_item() else {
cx.emit_err(session_diagnostics::UnsupportedLiteral {
span: param.span(),
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,21 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
call
}

fn tail_call(
&mut self,
_llty: Self::Type,
_fn_attrs: Option<&CodegenFnAttrs>,
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
_llfn: Self::Value,
_args: &[Self::Value],
_funclet: Option<&Self::Funclet>,
_instance: Option<Instance<'tcx>>,
) {
bug!(
"Guaranteed tail calls with the 'become' keyword are not implemented in the GCC backend"
);
}

fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
// FIXME(antoyo): this does not zero-extend.
self.gcc_int_cast(value, dest_typ)
Expand Down
26 changes: 25 additions & 1 deletion compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
Expand All @@ -24,7 +25,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_sanitizers::{cfi, kcfi};
use rustc_session::config::OptLevel;
use rustc_span::Span;
use rustc_target::callconv::FnAbi;
use rustc_target::callconv::{FnAbi, PassMode};
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
use smallvec::SmallVec;
use tracing::{debug, instrument};
Expand Down Expand Up @@ -1431,6 +1432,29 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
call
}

fn tail_call(
&mut self,
llty: Self::Type,
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
llfn: Self::Value,
args: &[Self::Value],
funclet: Option<&Self::Funclet>,
instance: Option<Instance<'tcx>>,
) {
let call = self.call(llty, fn_attrs, Some(fn_abi), llfn, args, funclet, instance);

match &fn_abi.ret.mode {
PassMode::Ignore | PassMode::Indirect { .. } => self.ret_void(),
PassMode::Direct(_) | PassMode::Pair { .. } => self.ret(call),
mode @ PassMode::Cast { .. } => {
bug!("Encountered `PassMode::{mode:?}` during codegen")
}
}

llvm::LLVMRustSetTailCallKind(call, llvm::TailCallKind::MustTail);
}

fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) }
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ pub(crate) enum ModuleFlagMergeBehavior {

// Consts for the LLVM CallConv type, pre-cast to usize.

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C)]
#[allow(dead_code)]
pub(crate) enum TailCallKind {
None = 0,
Tail = 1,
MustTail = 2,
NoTail = 3,
}

/// LLVM CallingConv::ID. Should we wrap this?
///
/// See <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/CallingConv.h>
Expand Down Expand Up @@ -1186,6 +1196,7 @@ unsafe extern "C" {
pub(crate) safe fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
pub(crate) safe fn LLVMRustSetTailCallKind(CallInst: &Value, Kind: TailCallKind);

// Operations on attributes
pub(crate) fn LLVMCreateStringAttribute(
Expand Down
134 changes: 106 additions & 28 deletions compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};

use rustc_abi::Endian;
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_hashes::Hash128;
use rustc_session::Session;
Expand Down Expand Up @@ -214,7 +214,7 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
/// It exports all the provided symbols, but is otherwise empty.
fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]) -> Vec<u8> {
use object::write::elf as write;
use object::{Architecture, elf};
use object::{AddressSize, Architecture, elf};

let mut stub_buf = Vec::new();

Expand All @@ -226,54 +226,94 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
// It is important that the order of reservation matches the order of writing.
// The object crate contains many debug asserts that fire if you get this wrong.

let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features)
else {
sess.dcx().fatal(format!(
"raw-dylib is not supported for the architecture `{}`",
sess.target.arch
));
};

let endianness = match sess.target.options.endian {
Endian::Little => object::Endianness::Little,
Endian::Big => object::Endianness::Big,
};
let mut stub = write::Writer::new(endianness, true, &mut stub_buf);

let is_64 = match arch.address_size() {
Some(AddressSize::U8 | AddressSize::U16 | AddressSize::U32) => false,
Some(AddressSize::U64) => true,
_ => sess.dcx().fatal(format!(
"raw-dylib is not supported for the architecture `{}`",
sess.target.arch
)),
};

let mut stub = write::Writer::new(endianness, is_64, &mut stub_buf);

let mut vers = Vec::new();
let mut vers_map = FxHashMap::default();
let mut syms = Vec::new();

for symbol in symbols {
let symbol_name = symbol.name.as_str();
if let Some((name, version_name)) = symbol_name.split_once('@') {
assert!(!version_name.contains('@'));
let dynstr = stub.add_dynamic_string(name.as_bytes());
let ver = if let Some(&ver_id) = vers_map.get(version_name) {
ver_id
} else {
let id = vers.len();
vers_map.insert(version_name, id);
let dynstr = stub.add_dynamic_string(version_name.as_bytes());
vers.push((version_name, dynstr));
id
};
syms.push((name, dynstr, Some(ver)));
} else {
let dynstr = stub.add_dynamic_string(symbol_name.as_bytes());
syms.push((symbol_name, dynstr, None));
}
}

let soname = stub.add_dynamic_string(soname.as_bytes());

// These initial reservations don't reserve any bytes in the binary yet,
// they just allocate in the internal data structures.

// First, we crate the dynamic symbol table. It starts with a null symbol
// First, we create the dynamic symbol table. It starts with a null symbol
// and then all the symbols and their dynamic strings.
stub.reserve_null_dynamic_symbol_index();

let dynstrs = symbols
.iter()
.map(|sym| {
stub.reserve_dynamic_symbol_index();
(sym, stub.add_dynamic_string(sym.name.as_str().as_bytes()))
})
.collect::<Vec<_>>();

let soname = stub.add_dynamic_string(soname.as_bytes());
for _ in syms.iter() {
stub.reserve_dynamic_symbol_index();
}

// Reserve the sections.
// We have the minimal sections for a dynamic SO and .text where we point our dummy symbols to.
stub.reserve_shstrtab_section_index();
let text_section_name = stub.add_section_name(".text".as_bytes());
let text_section = stub.reserve_section_index();
stub.reserve_dynstr_section_index();
stub.reserve_dynsym_section_index();
stub.reserve_dynstr_section_index();
if !vers.is_empty() {
stub.reserve_gnu_versym_section_index();
stub.reserve_gnu_verdef_section_index();
}
stub.reserve_dynamic_section_index();

// These reservations now determine the actual layout order of the object file.
stub.reserve_file_header();
stub.reserve_shstrtab();
stub.reserve_section_headers();
stub.reserve_dynstr();
stub.reserve_dynsym();
stub.reserve_dynstr();
if !vers.is_empty() {
stub.reserve_gnu_versym();
stub.reserve_gnu_verdef(1 + vers.len(), 1 + vers.len());
}
stub.reserve_dynamic(2); // DT_SONAME, DT_NULL

// First write the ELF header with the arch information.
let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features)
else {
sess.dcx().fatal(format!(
"raw-dylib is not supported for the architecture `{}`",
sess.target.arch
));
};
let e_machine = match (arch, sub_arch) {
(Architecture::Aarch64, None) => elf::EM_AARCH64,
(Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64,
Expand Down Expand Up @@ -342,18 +382,19 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
sh_addralign: 1,
sh_entsize: 0,
});
stub.write_dynstr_section_header(0);
stub.write_dynsym_section_header(0, 1);
stub.write_dynstr_section_header(0);
if !vers.is_empty() {
stub.write_gnu_versym_section_header(0);
stub.write_gnu_verdef_section_header(0);
}
stub.write_dynamic_section_header(0);

// .dynstr
stub.write_dynstr();

// .dynsym
stub.write_null_dynamic_symbol();
for (_, name) in dynstrs {
for (_name, dynstr, _ver) in syms.iter().copied() {
stub.write_dynamic_symbol(&write::Sym {
name: Some(name),
name: Some(dynstr),
st_info: (elf::STB_GLOBAL << 4) | elf::STT_NOTYPE,
st_other: elf::STV_DEFAULT,
section: Some(text_section),
Expand All @@ -363,10 +404,47 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
});
}

// .dynstr
stub.write_dynstr();

// ld.bfd is unhappy if these sections exist without any symbols, so we only generate them when necessary.
if !vers.is_empty() {
// .gnu_version
stub.write_null_gnu_versym();
for (_name, _dynstr, ver) in syms.iter().copied() {
stub.write_gnu_versym(if let Some(ver) = ver {
assert!((2 + ver as u16) < elf::VERSYM_HIDDEN);
elf::VERSYM_HIDDEN | (2 + ver as u16)
} else {
1
});
}

// .gnu_version_d
stub.write_align_gnu_verdef();
stub.write_gnu_verdef(&write::Verdef {
version: elf::VER_DEF_CURRENT,
flags: elf::VER_FLG_BASE,
index: 1,
aux_count: 1,
name: soname,
});
for (ver, (_name, dynstr)) in vers.into_iter().enumerate() {
stub.write_gnu_verdef(&write::Verdef {
version: elf::VER_DEF_CURRENT,
flags: 0,
index: 2 + ver as u16,
aux_count: 1,
name: dynstr,
});
}
}

// .dynamic
// the DT_SONAME will be used by the linker to populate DT_NEEDED
// which the loader uses to find the library.
// DT_NULL terminates the .dynamic table.
stub.write_align_dynamic();
stub.write_dynamic_string(elf::DT_SONAME, soname);
stub.write_dynamic(elf::DT_NULL, 0);

Expand Down
Loading
Loading