From b7d27822e3e295c34aacf389962ebe872697b9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 17 Jul 2025 09:15:17 +0200 Subject: [PATCH 1/5] Remove install Rust script from CI Windows ARM images should contain Rust now. --- .github/workflows/ci.yml | 3 --- src/ci/scripts/install-rust.sh | 15 --------------- 2 files changed, 18 deletions(-) delete mode 100755 src/ci/scripts/install-rust.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc8ac539a3a09..9d02787392814 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,9 +152,6 @@ jobs: - name: show the current environment run: src/ci/scripts/dump-environment.sh - - name: install rust - run: src/ci/scripts/install-rust.sh - - name: install awscli run: src/ci/scripts/install-awscli.sh diff --git a/src/ci/scripts/install-rust.sh b/src/ci/scripts/install-rust.sh deleted file mode 100755 index e4aee98c9fb2a..0000000000000 --- a/src/ci/scripts/install-rust.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# The Arm64 Windows Runner does not have Rust already installed -# https://github.com/actions/partner-runner-images/issues/77 - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if [[ "${CI_JOB_NAME}" = *aarch64* ]] && isWindows; then - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ - sh -s -- -y -q --default-host aarch64-pc-windows-msvc - ciCommandAddPath "${USERPROFILE}/.cargo/bin" -fi From c51e5ce452c96886bab78a8e736c750dd9e79fbd Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Thu, 31 Jul 2025 07:39:10 +0000 Subject: [PATCH 2/5] std_detect: Linux 6.16 support for RISC-V It adds feature detection of 1 extension (new in std_detect). New RISC-V Extension: 1. "Zabha" --- library/std_detect/src/detect/arch/riscv.rs | 3 +++ library/std_detect/src/detect/os/linux/riscv.rs | 8 +++++--- library/std_detect/src/detect/os/riscv.rs | 2 +- library/std_detect/tests/cpu-detection.rs | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/library/std_detect/src/detect/arch/riscv.rs b/library/std_detect/src/detect/arch/riscv.rs index b86190d7bbf0c..1d21b1d485589 100644 --- a/library/std_detect/src/detect/arch/riscv.rs +++ b/library/std_detect/src/detect/arch/riscv.rs @@ -73,6 +73,7 @@ features! { /// * Zihintpause: `"zihintpause"` /// * Zihpm: `"zihpm"` /// * Zimop: `"zimop"` + /// * Zabha: `"zabha"` /// * Zacas: `"zacas"` /// * Zawrs: `"zawrs"` /// * Zfa: `"zfa"` @@ -195,6 +196,8 @@ features! { /// "Zaamo" Extension for Atomic Memory Operations @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zawrs: "zawrs"; /// "Zawrs" Extension for Wait-on-Reservation-Set Instructions + @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zabha: "zabha"; + /// "Zabha" Extension for Byte and Halfword Atomic Memory Operations @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zacas: "zacas"; /// "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zam: "zam"; diff --git a/library/std_detect/src/detect/os/linux/riscv.rs b/library/std_detect/src/detect/os/linux/riscv.rs index dbb3664890e56..18f9f68ec67ef 100644 --- a/library/std_detect/src/detect/os/linux/riscv.rs +++ b/library/std_detect/src/detect/os/linux/riscv.rs @@ -10,13 +10,13 @@ use super::super::riscv::imply_features; use super::auxvec; use crate::detect::{Feature, bit, cache}; -// See +// See // for runtime status query constants. const PR_RISCV_V_GET_CONTROL: libc::c_int = 70; const PR_RISCV_V_VSTATE_CTRL_ON: libc::c_int = 2; const PR_RISCV_V_VSTATE_CTRL_CUR_MASK: libc::c_int = 3; -// See +// See // for riscv_hwprobe struct and hardware probing constants. #[repr(C)] @@ -98,6 +98,7 @@ const RISCV_HWPROBE_EXT_ZVFBFWMA: u64 = 1 << 54; const RISCV_HWPROBE_EXT_ZICBOM: u64 = 1 << 55; const RISCV_HWPROBE_EXT_ZAAMO: u64 = 1 << 56; const RISCV_HWPROBE_EXT_ZALRSC: u64 = 1 << 57; +const RISCV_HWPROBE_EXT_ZABHA: u64 = 1 << 58; const RISCV_HWPROBE_KEY_CPUPERF_0: i64 = 5; const RISCV_HWPROBE_MISALIGNED_FAST: u64 = 3; @@ -138,7 +139,7 @@ pub(crate) fn detect_features() -> cache::Initializer { // Use auxiliary vector to enable single-letter ISA extensions. // The values are part of the platform-specific [asm/hwcap.h][hwcap] // - // [hwcap]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwcap.h?h=v6.15 + // [hwcap]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/uapi/asm/hwcap.h?h=v6.16 let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform let mut has_i = bit::test(auxv.hwcap, (b'i' - b'a').into()); #[allow(clippy::eq_op)] @@ -233,6 +234,7 @@ pub(crate) fn detect_features() -> cache::Initializer { enable_feature(Feature::zalrsc, test(RISCV_HWPROBE_EXT_ZALRSC)); enable_feature(Feature::zaamo, test(RISCV_HWPROBE_EXT_ZAAMO)); enable_feature(Feature::zawrs, test(RISCV_HWPROBE_EXT_ZAWRS)); + enable_feature(Feature::zabha, test(RISCV_HWPROBE_EXT_ZABHA)); enable_feature(Feature::zacas, test(RISCV_HWPROBE_EXT_ZACAS)); enable_feature(Feature::ztso, test(RISCV_HWPROBE_EXT_ZTSO)); diff --git a/library/std_detect/src/detect/os/riscv.rs b/library/std_detect/src/detect/os/riscv.rs index dc9a4036d86a1..c6acbd3525bd3 100644 --- a/library/std_detect/src/detect/os/riscv.rs +++ b/library/std_detect/src/detect/os/riscv.rs @@ -90,7 +90,7 @@ pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initialize group!(zks == zbkb & zbkc & zbkx & zksed & zksh); group!(zk == zkn & zkr & zkt); - imply!(zacas => zaamo); + imply!(zabha | zacas => zaamo); group!(a == zalrsc & zaamo); group!(b == zba & zbb & zbs); diff --git a/library/std_detect/tests/cpu-detection.rs b/library/std_detect/tests/cpu-detection.rs index 5ad32d83237ce..0c4fa57f2b465 100644 --- a/library/std_detect/tests/cpu-detection.rs +++ b/library/std_detect/tests/cpu-detection.rs @@ -242,6 +242,7 @@ fn riscv_linux() { println!("zalrsc: {}", is_riscv_feature_detected!("zalrsc")); println!("zaamo: {}", is_riscv_feature_detected!("zaamo")); println!("zawrs: {}", is_riscv_feature_detected!("zawrs")); + println!("zabha: {}", is_riscv_feature_detected!("zabha")); println!("zacas: {}", is_riscv_feature_detected!("zacas")); println!("zam: {}", is_riscv_feature_detected!("zam")); println!("ztso: {}", is_riscv_feature_detected!("ztso")); From 7a127fba657ed627cc4877f2871abaf7d9819caa Mon Sep 17 00:00:00 2001 From: Flakebi Date: Fri, 28 Mar 2025 10:15:56 +0100 Subject: [PATCH 3/5] Fix linker-plugin-lto only doing thin lto When rust provides LLVM bitcode files to lld and the bitcode contains function summaries as used for thin lto, lld defaults to using thin lto. This prevents some optimizations that are only applied for fat lto. We solve this by not creating function summaries when fat lto is enabled. The bitcode for the module is just directly written out. An alternative solution would be to set the `ThinLTO=0` module flag to signal lld to do fat lto. The code in clang that sets this flag is here: https://github.com/llvm/llvm-project/blob/560149b5e3c891c64899e9912e29467a69dc3a4c/clang/lib/CodeGen/BackendUtil.cpp#L1150 The code in LLVM that queries the flag and defaults to thin lto if not set is here: https://github.com/llvm/llvm-project/blob/e258bca9505f35e0a22cb213a305eea9b76d11ea/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp#L4441-L4446 --- compiler/rustc_codegen_ssa/src/back/write.rs | 4 +- .../src/external_deps/llvm.rs | 30 ++++++++++ .../src/external_deps/rustc.rs | 6 ++ src/tools/run-make-support/src/lib.rs | 5 +- tests/run-make/cross-lang-lto-clang/rmake.rs | 59 ++++++++++++------- tests/run-make/fat-then-thin-lto/lib.rs | 13 ++++ tests/run-make/fat-then-thin-lto/main.rs | 11 ++++ tests/run-make/fat-then-thin-lto/rmake.rs | 25 ++++++++ tests/run-make/linker-plugin-lto-fat/ir.ll | 6 ++ tests/run-make/linker-plugin-lto-fat/main.rs | 22 +++++++ tests/run-make/linker-plugin-lto-fat/rmake.rs | 33 +++++++++++ 11 files changed, 189 insertions(+), 25 deletions(-) create mode 100644 tests/run-make/fat-then-thin-lto/lib.rs create mode 100644 tests/run-make/fat-then-thin-lto/main.rs create mode 100644 tests/run-make/fat-then-thin-lto/rmake.rs create mode 100644 tests/run-make/linker-plugin-lto-fat/ir.ll create mode 100644 tests/run-make/linker-plugin-lto-fat/main.rs create mode 100644 tests/run-make/linker-plugin-lto-fat/rmake.rs diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7be274df1d41d..0394ddf2bee93 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -215,7 +215,9 @@ impl ModuleConfig { false ), emit_obj, - emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto, + // thin lto summaries prevent fat lto, so do not emit them if fat + // lto is requested. See PR #136840 for background information. + emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto && sess.lto() != Lto::Fat, emit_thin_lto_summary: if_regular!( sess.opts.output_types.contains_key(&OutputType::ThinLinkBitcode), false diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 9a6e35da3fe20..939160d9f41d8 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -60,6 +60,12 @@ pub fn llvm_pdbutil() -> LlvmPdbutil { LlvmPdbutil::new() } +/// Construct a new `llvm-as` invocation. This assumes that `llvm-as` is available +/// at `$LLVM_BIN_DIR/llvm-as`. +pub fn llvm_as() -> LlvmAs { + LlvmAs::new() +} + /// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available /// at `$LLVM_BIN_DIR/llvm-dis`. pub fn llvm_dis() -> LlvmDis { @@ -135,6 +141,13 @@ pub struct LlvmPdbutil { cmd: Command, } +/// A `llvm-as` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmAs { + cmd: Command, +} + /// A `llvm-dis` invocation builder. #[derive(Debug)] #[must_use] @@ -158,6 +171,7 @@ crate::macros::impl_common_helpers!(LlvmNm); crate::macros::impl_common_helpers!(LlvmBcanalyzer); crate::macros::impl_common_helpers!(LlvmDwarfdump); crate::macros::impl_common_helpers!(LlvmPdbutil); +crate::macros::impl_common_helpers!(LlvmAs); crate::macros::impl_common_helpers!(LlvmDis); crate::macros::impl_common_helpers!(LlvmObjcopy); @@ -441,6 +455,22 @@ impl LlvmObjcopy { } } +impl LlvmAs { + /// Construct a new `llvm-as` invocation. This assumes that `llvm-as` is available + /// at `$LLVM_BIN_DIR/llvm-as`. + pub fn new() -> Self { + let llvm_as = llvm_bin_dir().join("llvm-as"); + let cmd = Command::new(llvm_as); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} + impl LlvmDis { /// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available /// at `$LLVM_BIN_DIR/llvm-dis`. 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 08ba1388dc148..60d3366ee98c8 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -173,6 +173,12 @@ impl Rustc { self } + /// This flag enables LTO in the specified form. + pub fn lto(&mut self, option: &str) -> &mut Self { + self.cmd.arg(format!("-Clto={option}")); + self + } + /// This flag defers LTO optimizations to the linker. pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self { self.cmd.arg(format!("-Clinker-plugin-lto={option}")); diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 29cd6c4ad1591..b7d89b130c6ba 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -63,8 +63,9 @@ pub use crate::external_deps::clang::{Clang, clang}; pub use crate::external_deps::htmldocck::htmldocck; pub use crate::external_deps::llvm::{ self, LlvmAr, LlvmBcanalyzer, LlvmDis, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjcopy, - LlvmObjdump, LlvmProfdata, LlvmReadobj, llvm_ar, llvm_bcanalyzer, llvm_dis, llvm_dwarfdump, - llvm_filecheck, llvm_nm, llvm_objcopy, llvm_objdump, llvm_profdata, llvm_readobj, + LlvmObjdump, LlvmProfdata, LlvmReadobj, llvm_ar, llvm_as, llvm_bcanalyzer, llvm_dis, + llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objcopy, llvm_objdump, llvm_profdata, + llvm_readobj, }; pub use crate::external_deps::python::python_command; pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_path}; diff --git a/tests/run-make/cross-lang-lto-clang/rmake.rs b/tests/run-make/cross-lang-lto-clang/rmake.rs index 3fed6ea20667a..f209318abbcc1 100644 --- a/tests/run-make/cross-lang-lto-clang/rmake.rs +++ b/tests/run-make/cross-lang-lto-clang/rmake.rs @@ -28,7 +28,17 @@ static C_NEVER_INLINED_PATTERN: &'static str = "bl.*"; static C_NEVER_INLINED_PATTERN: &'static str = "call.*c_never_inlined"; fn main() { + test_lto(false); + test_lto(true); +} + +fn test_lto(fat_lto: bool) { + let lto = if fat_lto { "fat" } else { "thin" }; + let clang_lto = if fat_lto { "full" } else { "thin" }; + println!("Running {lto} lto"); + rustc() + .lto(lto) .linker_plugin_lto("on") .output(static_lib_name("rustlib-xlto")) .opt_level("2") @@ -36,30 +46,36 @@ fn main() { .input("rustlib.rs") .run(); clang() - .lto("thin") + .lto(clang_lto) .use_ld("lld") .arg("-lrustlib-xlto") .out_exe("cmain") .input("cmain.c") .arg("-O3") .run(); + + let dump = llvm_objdump().disassemble().input("cmain").run(); // Make sure we don't find a call instruction to the function we expect to // always be inlined. - llvm_objdump() - .disassemble() - .input("cmain") - .run() - .assert_stdout_not_contains_regex(RUST_ALWAYS_INLINED_PATTERN); + dump.assert_stdout_not_contains_regex(RUST_ALWAYS_INLINED_PATTERN); // As a sanity check, make sure we do find a call instruction to a // non-inlined function - llvm_objdump() - .disassemble() - .input("cmain") - .run() - .assert_stdout_contains_regex(RUST_NEVER_INLINED_PATTERN); - clang().input("clib.c").lto("thin").arg("-c").out_exe("clib.o").arg("-O2").run(); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + dump.assert_stdout_contains_regex(RUST_NEVER_INLINED_PATTERN); + #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + { + if fat_lto { + // fat lto inlines this anyway + dump.assert_stdout_not_contains_regex(RUST_NEVER_INLINED_PATTERN); + } else { + dump.assert_stdout_contains_regex(RUST_NEVER_INLINED_PATTERN); + } + } + + clang().input("clib.c").lto(clang_lto).arg("-c").out_exe("clib.o").arg("-O2").run(); llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); rustc() + .lto(lto) .linker_plugin_lto("on") .opt_level("2") .linker(&env_var("CLANG")) @@ -67,14 +83,13 @@ fn main() { .input("main.rs") .output("rsmain") .run(); - llvm_objdump() - .disassemble() - .input("rsmain") - .run() - .assert_stdout_not_contains_regex(C_ALWAYS_INLINED_PATTERN); - llvm_objdump() - .disassemble() - .input("rsmain") - .run() - .assert_stdout_contains_regex(C_NEVER_INLINED_PATTERN); + + let dump = llvm_objdump().disassemble().input("rsmain").run(); + dump.assert_stdout_not_contains_regex(C_ALWAYS_INLINED_PATTERN); + if fat_lto { + // fat lto inlines this anyway + dump.assert_stdout_not_contains_regex(C_NEVER_INLINED_PATTERN); + } else { + dump.assert_stdout_contains_regex(C_NEVER_INLINED_PATTERN); + } } diff --git a/tests/run-make/fat-then-thin-lto/lib.rs b/tests/run-make/fat-then-thin-lto/lib.rs new file mode 100644 index 0000000000000..c675dcb6e8a84 --- /dev/null +++ b/tests/run-make/fat-then-thin-lto/lib.rs @@ -0,0 +1,13 @@ +#![allow(internal_features)] +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "rlib"] + +#[lang = "pointee_sized"] +trait PointeeSized {} +#[lang = "meta_sized"] +trait MetaSized: PointeeSized {} +#[lang = "sized"] +trait Sized: MetaSized {} + +pub fn foo() {} diff --git a/tests/run-make/fat-then-thin-lto/main.rs b/tests/run-make/fat-then-thin-lto/main.rs new file mode 100644 index 0000000000000..a3f2e18158bc0 --- /dev/null +++ b/tests/run-make/fat-then-thin-lto/main.rs @@ -0,0 +1,11 @@ +#![allow(internal_features)] +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "cdylib"] + +extern crate lib; + +#[unsafe(no_mangle)] +pub fn bar() { + lib::foo(); +} diff --git a/tests/run-make/fat-then-thin-lto/rmake.rs b/tests/run-make/fat-then-thin-lto/rmake.rs new file mode 100644 index 0000000000000..ef4f26689d4e8 --- /dev/null +++ b/tests/run-make/fat-then-thin-lto/rmake.rs @@ -0,0 +1,25 @@ +// Compile a library with lto=fat, then compile a binary with lto=thin +// and check that lto is applied with the library. +// The goal is to mimic the standard library being build with lto=fat +// and allowing users to build with lto=thin. + +//@ only-x86_64-unknown-linux-gnu + +use run_make_support::{dynamic_lib_name, llvm_objdump, rustc}; + +fn main() { + rustc().input("lib.rs").opt_level("3").lto("fat").run(); + rustc().input("main.rs").panic("abort").opt_level("3").lto("thin").run(); + + llvm_objdump() + .input(dynamic_lib_name("main")) + .arg("--disassemble-symbols=bar") + .run() + // The called function should be inlined. + // Check that we have a ret (to detect tail + // calls with a jmp) and no call. + .assert_stdout_contains("bar") + .assert_stdout_contains("ret") + .assert_stdout_not_contains("foo") + .assert_stdout_not_contains("call"); +} diff --git a/tests/run-make/linker-plugin-lto-fat/ir.ll b/tests/run-make/linker-plugin-lto-fat/ir.ll new file mode 100644 index 0000000000000..fa3dbdd4e088d --- /dev/null +++ b/tests/run-make/linker-plugin-lto-fat/ir.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @ir_callee() { + ret void +} diff --git a/tests/run-make/linker-plugin-lto-fat/main.rs b/tests/run-make/linker-plugin-lto-fat/main.rs new file mode 100644 index 0000000000000..ad2a90bc80190 --- /dev/null +++ b/tests/run-make/linker-plugin-lto-fat/main.rs @@ -0,0 +1,22 @@ +#![allow(internal_features)] +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "cdylib"] + +#[lang = "pointee_sized"] +trait PointeeSized {} +#[lang = "meta_sized"] +trait MetaSized: PointeeSized {} +#[lang = "sized"] +trait Sized: MetaSized {} + +extern "C" { + fn ir_callee(); +} + +#[no_mangle] +extern "C" fn rs_foo() { + unsafe { + ir_callee(); + } +} diff --git a/tests/run-make/linker-plugin-lto-fat/rmake.rs b/tests/run-make/linker-plugin-lto-fat/rmake.rs new file mode 100644 index 0000000000000..ff5b647a5941f --- /dev/null +++ b/tests/run-make/linker-plugin-lto-fat/rmake.rs @@ -0,0 +1,33 @@ +// Check that -C lto=fat with -C linker-plugin-lto actually works and can inline functions. +// A library is created from LLVM IR, defining a single function. Then a dylib is compiled, +// linking to the library and calling the function from the library. +// The function from the library should end up inlined and disappear from the output. + +//@ only-x86_64-unknown-linux-gnu +//@ needs-rust-lld + +use run_make_support::{dynamic_lib_name, llvm_as, llvm_objdump, rustc}; + +fn main() { + llvm_as().input("ir.ll").run(); + rustc() + .input("main.rs") + .opt_level("3") + .lto("fat") + .linker_plugin_lto("on") + .link_arg("ir.bc") + .arg("-Zunstable-options") + .arg("-Clinker-features=+lld") + .run(); + + llvm_objdump() + .input(dynamic_lib_name("main")) + .arg("--disassemble-symbols=rs_foo") + .run() + // The called function should be inlined. + // Check that we have a ret (to detect tail + // calls with a jmp) and no call. + .assert_stdout_contains("foo") + .assert_stdout_contains("ret") + .assert_stdout_not_contains("call"); +} From 227abb70ab2e3d10f05fe933d3c77ecbb04eb9a9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 22 Jul 2025 12:03:15 +0200 Subject: [PATCH 4/5] Make `libtest::ERROR_EXIT_CODE` const public to not redefine it in rustdoc --- library/test/src/lib.rs | 4 ++-- src/librustdoc/doctest.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 7f56d1e362698..1190bb56b97a0 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -89,8 +89,8 @@ use options::RunStrategy; use test_result::*; use time::TestExecTime; -// Process exit code to be used to indicate test failures. -const ERROR_EXIT_CODE: i32 = 101; +/// Process exit code to be used to indicate test failures. +pub const ERROR_EXIT_CODE: i32 = 101; const SECONDARY_TEST_INVOKER_VAR: &str = "__RUST_TEST_INVOKE"; const SECONDARY_TEST_BENCH_BENCHMARKS_VAR: &str = "__RUST_TEST_BENCH_BENCHMARKS"; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 0bef091468f2b..a4344c87e028d 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -410,7 +410,7 @@ pub(crate) fn run_tests( std::mem::drop(temp_dir); times.display_times(); // libtest::ERROR_EXIT_CODE is not public but it's the same value. - std::process::exit(101); + std::process::exit(test::ERROR_EXIT_CODE); } } From bee5fbf36e9cbb7f3317ce6a71b3574dc007dee5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 22 Jul 2025 13:31:12 +0200 Subject: [PATCH 5/5] Fix CI build failure when using new libtest public constant --- src/librustdoc/doctest.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a4344c87e028d..35ace6566381b 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -409,8 +409,9 @@ pub(crate) fn run_tests( // We ensure temp dir destructor is called. std::mem::drop(temp_dir); times.display_times(); - // libtest::ERROR_EXIT_CODE is not public but it's the same value. - std::process::exit(test::ERROR_EXIT_CODE); + // FIXME(GuillaumeGomez): Uncomment the next line once #144297 has been merged. + // std::process::exit(test::ERROR_EXIT_CODE); + std::process::exit(101); } }