From 0e58273c323f221f1c0f009c74edf9191b9a5ff5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:39:57 +0200 Subject: [PATCH 01/28] Merge commit 'bb351cd4ddf59d8a9b5c086a15e41bc6a1c05b5f' into sync_cg_clif-2026-08-19 --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ff51f49edc4ca..ea4ff67c93c89 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-08-17" +channel = "nightly-2026-08-19" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 1aa628913f2d2e6b1ae58ceaa1ecba6a4b4b9c06 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:59:33 +0200 Subject: [PATCH 02/28] move CrateType --- src/driver/jit.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 32f60615844bc..8bf1cd9bf85bc 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -37,7 +37,7 @@ fn create_jit_module( } pub(crate) fn run_jit(tcx: TyCtxt<'_>, target_cpu: String, jit_args: Vec) -> ! { - if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) { + if !tcx.crate_types().contains(&rustc_structures::CrateType::Executable) { tcx.dcx().fatal("can't jit non-executable crate"); } @@ -180,7 +180,7 @@ fn dep_symbol_lookup_fn( let mut dylib_paths = Vec::new(); - let data = &crate_info.dependency_formats[&rustc_session::config::CrateType::Executable]; + let data = &crate_info.dependency_formats[&rustc_structures::CrateType::Executable]; // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library From 01c4315ac4f8348c6ec8d6ac3665342a03971a1b Mon Sep 17 00:00:00 2001 From: Rudraksh Joshi Date: Fri, 21 Aug 2026 21:39:26 +0530 Subject: [PATCH 03/28] Remove LD_STATIC_TLS_EXTRA workaround from FreeBSD CI --- .github/workflows/freebsd.yml | 3 --- Readme.md | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index f344113aa7fdf..e0b2bd34631f9 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -34,8 +34,5 @@ jobs: # Disabling incr comp reduces cache size and incr comp doesn't save # as much on CI anyway. export CARGO_BUILD_INCREMENTAL=false - # FIXME(rust-lang/rust#134863) necessary to avoid error when - # dlopening proc macros during compilation of cg_clif. - export LD_STATIC_TLS_EXTRA=4096 # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 ./y.sh test --skip-test test.rust-random/rand diff --git a/Readme.md b/Readme.md index c5436cf67c80a..48003ad270e6f 100644 --- a/Readme.md +++ b/Readme.md @@ -66,7 +66,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system |OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)| |---|---|---|---|---| |Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]| -|FreeBSD|✅[^no-rustup][^tls]|❓|❓|❓| +|FreeBSD|✅[^no-rustup]|❓|❓|❓| |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| |Other unixes|❓|❓|❓|❓| |macOS|✅|✅|N/A|N/A| @@ -80,7 +80,6 @@ Not all targets are available as rustup component for nightly. See notes in the [^xcoff]: XCOFF object file format is not supported. [^no-rustup]: Not available as [rustup component for nightly](https://rust-lang.github.io/rustup-components-history/). You can build it yourself. -[^tls]: FreeBSD requires setting `LD_STATIC_TLS_EXTRA=4096` to build cg_clif. In addition you need at least FreeBSD 14. ## Usage From 945a71a6c4782621dcaed1a633b89dfdfdad7720 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 29 Jul 2026 11:10:21 +0200 Subject: [PATCH 04/28] make `pad_i32` of `PassMode::cast` an integer so that we can specify more than one i32 of padding. --- src/abi/pass_mode.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index c4d4ddcf6b753..1c552ca1a9c32 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -122,8 +122,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { } _ => unreachable!("{:?}", self.layout.backend_repr), }, - PassMode::Cast { ref cast, pad_i32 } => { - assert!(!pad_i32, "padding support not yet implemented"); + PassMode::Cast { ref cast, pad_i32_count } => { + assert_eq!(pad_i32_count, 0, "padding support not yet implemented"); cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect() } PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { From a299bc115f895ab38e874c8e499a5e79edf2e404 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:06:36 +0200 Subject: [PATCH 05/28] Rustup to rustc 1.100.0-nightly (fb6531d55 2026-08-23) --- build_system/build_sysroot.rs | 1 - rust-toolchain.toml | 2 +- src/lib.rs | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 71c0523615ff1..3ac7724f8f318 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -252,7 +252,6 @@ fn build_clif_sysroot_for_target( build_cmd.arg("--features").arg("backtrace panic-unwind"); build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display())); build_cmd.arg("-Zembed-metadata=no"); - build_cmd.arg("-Zbuild-dir-new-layout"); build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true"); build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); if compiler.target.contains("apple") { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ea4ff67c93c89..e203b3305eda1 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-08-19" +channel = "nightly-2026-08-24" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/src/lib.rs b/src/lib.rs index 71fce9e28f120..d00631e5ab543 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ extern crate rustc_index; extern crate rustc_log; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_structures; extern crate rustc_symbol_mangling; extern crate rustc_target; From 19946d3e45939e67a32fb9e52dc94bd9b9fd7832 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:34:35 +0200 Subject: [PATCH 06/28] Fix rustc test suite --- scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 3885561e94a1e..4db6fe35f65c6 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -174,6 +174,7 @@ rm tests/ui/process/println-with-broken-pipe.rs # same rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort rm -r tests/run-make/used-proc-macro # doesn't work on arm64 for some reason +rm tests/ui/async-await/async-drop/async-drop-async-gen-return-pending.rs # rustc side fnsig issue # bugs in the test suite # ====================== From b5534e25c52eb7a473534cea604701f7cb91d32d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Aug 2026 15:06:32 +0200 Subject: [PATCH 07/28] Fix warning --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index d00631e5ab543..6d2a353745235 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ extern crate rustc_index; extern crate rustc_log; extern crate rustc_session; extern crate rustc_span; +#[cfg(feature = "jit")] extern crate rustc_structures; extern crate rustc_symbol_mangling; extern crate rustc_target; From 2bc05d45078dbee6495c008cbd5d1dc24edff53f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Aug 2026 11:21:09 +0200 Subject: [PATCH 08/28] Update to Cranelift 0.135 Co-Authored-By: Mads Marquart --- Cargo.lock | 77 ++++++++++++++++++++--------------------- Cargo.toml | 24 ++++++------- src/constant.rs | 44 +---------------------- src/debuginfo/unwind.rs | 2 +- 4 files changed, 52 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88ea75a6b0299..80bbbfe4e9bc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,27 +43,27 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cranelift-assembler-x64" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25c5b1bb1d86ae68dca1826a1b668b9951056c42e0eef89e35942c7001eb481" +checksum = "a4a59ddc4abd9c5560f4742864b2cd8c19e73c7263f0c866b2c45c2d31587adc" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b052a1fd94b4565697c56f9d358723c7c354feef42a6569081225c1bed6e86" +checksum = "8a8c361cd22fd0fdd8e61af6bfd86ad9c0c62f78b2b1caa2b9e4e97cd8f605fe" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a599e8ffa6a1a118d2dce4809073ad2f2534b1ae1c6d55697b6b8a324446c971" +checksum = "b86c34ae183cf2410318f899648fe1ef6ab9148486e7b938d7b4d814e61dafc9" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -71,18 +71,18 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e1ae13182fadc731b1387287b4c6d257b9191fbb7c980ebb2d74c2db74b743e" +checksum = "415f1a12668869e16ac3b66a729fb8cce8bbe6e50e68d1fa0142acd0c9c05f0c" dependencies = [ "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce9c62e5e11d12f4a8f5f939f29899f32002d38193b47491e2539705a1d447e" +checksum = "73eecedc85ffca4f34dbe197c6545c8ade6579a61352457936f53c3bffa6353b" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c29d6b53cfd758dc1a269310fc92199056db03943b9b774b4911cd615e02ad7" +checksum = "66834005198c3e9e3d89cd69cf1541419402ab75250afbeaa3128db6d5254025" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -119,24 +119,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd8cfe23f3349bfa62e06a450cd94cf5f84fbe78556f4df3276534c4b93d834" +checksum = "7e6efaf74077091a2ff41317cc8eb2779264dae4b8a16d955835f3fcda338f52" [[package]] name = "cranelift-control" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f991b4712f21d9502758f7e6cb11746ca2e6186b06c42995eaf31b1e50a9c498" +checksum = "a4258d4ed6ad4e698fe1fec4277b1fcbea6f2a17cb5ec3f04bddfb38ca83d93e" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e24f9c233a43730e22cf42ab0c03f41265e147eca97b3362be01e0da359d7a5" +checksum = "4f016b6f87b1a46a3f5df59b82d88bb352bf2fa6d7868875dfc4d6b65de5242d" dependencies = [ "cranelift-bitset", "wasmtime-internal-core", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61325401051d35ddbf8e2b5d5b5dec8dd54688c9054046b62e76146e61c88a99" +checksum = "b16f2b149dae6ea3886bee931445196d86d8e71b66f7c3b21abe434f77189be8" dependencies = [ "cranelift-codegen", "hashbrown 0.17.0", @@ -157,15 +157,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f71d642812aa70284750719efbd2cc5ad7e7c5e6c43c026b5b0686ce8a6052" +checksum = "f00258ff3d37f52ed731df679205e66175c728846dbde186ee20e93973d12ee7" [[package]] name = "cranelift-jit" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a0f9300c8a5738553a440fe4f25b85f574d5c41b946880dabd47c809f87997" +checksum = "fa063cc98af51fb9090cd40b674503e21bdfa705d2bff75ebf98b79ffc0f598d" dependencies = [ "anyhow", "cranelift-codegen", @@ -184,9 +184,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f723983af35e690c4e2fc160df5d8895bb4a419a54d693367163d781bd830cc" +checksum = "bff0025f1ff6a0470cbd2a61b125f8501311ea9e6c46ed5bb2110ee6710c6a76" dependencies = [ "anyhow", "cranelift-codegen", @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c50cffac70c30cc5d0b1d8d287e7712dc76b1181c43697de63d27f38236ddd" +checksum = "4f31eb7e08f31e5bc9c167c35718b0325efa3d4e234e2e9342316e01b18a4b51" dependencies = [ "cranelift-codegen", "libc", @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "430e18f4886ba98f6a7dbb82c86df19f28f27cac417611e5dcc427a7a8decac9" +checksum = "7ca0d86955529d5b9041c4c07745f6ffa42c32326e9f467a834e2b7bd9a9d156" dependencies = [ "anyhow", "cranelift-codegen", @@ -221,9 +221,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.134.0" +version = "0.135.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5972dc0a5df7ba6f11e8e1654287c40ea1704ca6ce3b76ef54fa58445ee4ad" +checksum = "2e0b67d313f510520f40c1496c3446af0d6b30219d1ba9a4c09c77ec288a561b" [[package]] name = "crc32fast" @@ -379,9 +379,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2c52737737f8609e94f975dee22854a2d5c125772d4b1cf292120f4d45c186" +checksum = "757712e8e61590d6d4f5d563483755538b5aa13467837a3b41cd9832509a7f85" dependencies = [ "allocator-api2", "bumpalo", @@ -493,9 +493,9 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "wasmtime-internal-core" -version = "47.0.0" +version = "48.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852f3326264aea590131a422e3ecb33fae3b6695fd67e2e202e2799cd8d27629" +checksum = "2c01c81d781512e17b38c3a76ca9aa2564bc3f9fd8ff6ffc77ba3e1c290d488a" dependencies = [ "hashbrown 0.17.0", "libm", @@ -503,11 +503,10 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "47.0.0" +version = "48.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e537f59b5ab127ca2d421ecbd8728d70bd6cdc9891cec193fb1f594c3309836c" +checksum = "2a09abde04346919af1136a28f344e200685509e28815aef4c39dc08977cc1d8" dependencies = [ - "cfg-if", "libc", "wasmtime-internal-core", "windows-sys 0.61.2", diff --git a/Cargo.toml b/Cargo.toml index cb595332bac61..ca03be20cd100 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.134.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.134.0" } -cranelift-module = { version = "0.134.0" } -cranelift-native = { version = "0.134.0" } -cranelift-jit = { version = "0.134.0", optional = true } -cranelift-object = { version = "0.134.0", default-features = false } +cranelift-codegen = { version = "0.135.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.135.0" } +cranelift-module = { version = "0.135.0" } +cranelift-native = { version = "0.135.0" } +cranelift-jit = { version = "0.135.0", optional = true } +cranelift-object = { version = "0.135.0", default-features = false } target-lexicon = "0.13" gimli = { version = "0.33", default-features = false, features = ["write"] } object = { version = "0.39.1", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" # Uncomment to use an unreleased version of cranelift #[patch.crates-io] -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-47.0.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-48.0.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/src/constant.rs b/src/constant.rs index b1cb5f30cbdfe..e2b0035361733 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -415,49 +415,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant data.set_align(alloc.align.bytes()); if let Some(section_name) = section_name { - let (segment_name, section_name) = if tcx.sess.target.is_like_darwin { - // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp - let mut parts = section_name.as_str().split(','); - let Some(segment_name) = parts.next() else { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma", - section_name - )); - }; - let Some(section_name) = parts.next() else { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma", - section_name - )); - }; - if section_name.len() > 16 { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: section name bigger than 16 bytes", - section_name - )); - } - let section_type = parts.next().unwrap_or("regular"); - if section_type != "regular" && section_type != "cstring_literals" { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not supported: unsupported section type {}", - section_name, section_type, - )); - } - let _attrs = parts.next(); - if parts.next().is_some() { - tcx.dcx().fatal(format!( - "#[link_section = \"{}\"] is not valid for macos target: too many components", - section_name - )); - } - // FIXME(bytecodealliance/wasmtime#8901) set S_CSTRING_LITERALS section type when - // cstring_literals is specified - (segment_name, section_name) - } else { - ("", section_name.as_str()) - }; - // FIXME pass correct section flags on Mach-O - data.set_segment_section(segment_name, section_name, 0); + data.set_custom_section(section_name.as_str()); } let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); diff --git a/src/debuginfo/unwind.rs b/src/debuginfo/unwind.rs index 4b0260a8abc74..ad0a15bf7f6e5 100644 --- a/src/debuginfo/unwind.rs +++ b/src/debuginfo/unwind.rs @@ -204,7 +204,7 @@ impl UnwindContext { let mut data = DataDescription::new(); data.define(gcc_except_table.writer.into_vec().into_boxed_slice()); - data.set_segment_section("", ".gcc_except_table", 0); + data.set_custom_section(".gcc_except_table"); for reloc in &gcc_except_table.relocs { match reloc.name { From 9a1ef58bc1bf4d2350e877f1b70c40c3893f2128 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Wed, 26 Aug 2026 16:37:36 +0200 Subject: [PATCH 09/28] Add missing self-profile-event option and information about default options to help message The `query-cache-hit-count` option was forgotten to be added to the help text when it was added. The new help text also documents which of the options are part of `default`, and now conveys the information that `args` is also a compound/group option as well as what it contains. --- compiler/rustc_data_structures/src/profiling.rs | 2 ++ compiler/rustc_session/src/options.rs | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 00fb424cadfd1..41e5f7ae67ab0 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -120,6 +120,7 @@ bitflags::bitflags! { /// Store aggregated counts of cache hits per query invocation. const QUERY_CACHE_HIT_COUNTS = 1 << 10; + // keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs const DEFAULT = Self::GENERIC_ACTIVITIES.bits() | Self::QUERY_PROVIDERS.bits() | Self::QUERY_BLOCKED.bits() | @@ -128,6 +129,7 @@ bitflags::bitflags! { Self::ARTIFACT_SIZES.bits() | Self::QUERY_CACHE_HIT_COUNTS.bits(); + // keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs const ARGS = Self::QUERY_KEYS.bits() | Self::FUNCTION_ARGS.bits(); const QUERY_CACHE_HIT_COMBINED = Self::QUERY_CACHE_HITS.bits() | Self::QUERY_CACHE_HIT_COUNTS.bits(); } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 90459090ced87..753eebdb3f39f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2843,8 +2843,11 @@ written to standard error output)"), self_profile_events: Option> = (None, parse_opt_comma_list, [UNTRACKED], "specify the events recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` - all options: none, all, default, generic-activity, query-provider, query-cache-hit - query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"), + all option groups: none, all, default, args + `default` contains: generic-activity, query-provider, query-cache-hit-count, \ + query-blocked, incr-cache-load, incr-result-hashing, artifact-sizes + `args` contains: query-keys, function-args + remaining (ungrouped) options: query-cache-hit, llvm"), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), shell_argfiles: bool = (false, parse_bool, [UNTRACKED], From e960d5e379d55ee779a20b9a8eadfc332320b6d9 Mon Sep 17 00:00:00 2001 From: Aapo Alasuutari Date: Thu, 27 Aug 2026 20:03:59 +0000 Subject: [PATCH 10/28] fix(reborrow): recursive implementation * Implement Reborrow as a recursive operation If Reborrow finds '&'a mut T' fields then it inserts a Deref and borrow of the T, and likewise if it finds a 'T: Reborrow' field then the field type is recursed into. This makes Reborrow always produce the correct borrow checking logic at the cost of most probably being inconsiderately expensive. The thinking is that performance will be a followup consideration. * PhantomDeref * Simpler deref test * Add more PhantomDeref unreachability assertions * Write out lifetime omission * Document ProjectionElem::PhantomDeref * Comment half of reborrow tests * fix PhantomDeref conflicting with AccessDepth::Shallow * Recheck CoerceShared in borrowck TypeChecker to ensure its lifetimes make sense * Fix rebase * Changes... but where to? * Typo fix * Improve comment * Use fully_perform_op to evaluate CoerceShared trait in borrowck * More CoerceShared comment * Comment rest of Reborrow tests Co-authored-by: Oli Scherer --- src/base.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base.rs b/src/base.rs index 27bb19c8d53c5..f9cf35e754ea0 100644 --- a/src/base.rs +++ b/src/base.rs @@ -994,6 +994,7 @@ pub(crate) fn codegen_place<'tcx>( PlaceElem::Deref => { cplace = cplace.place_deref(fx); } + PlaceElem::PhantomDeref => bug!("encountered PhantomDeref in codegen"), PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"), PlaceElem::UnwrapUnsafeBinder(ty) => { cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)); From 61f4a731ec249984831214acde275e62ae53bd51 Mon Sep 17 00:00:00 2001 From: Hanna Kruppe Date: Sat, 29 Aug 2026 13:32:29 +0200 Subject: [PATCH 11/28] Remove -Zsaturating-float-casts flag I added this flag back in 2017 to enable benchmarking of the saturating semantics when it was newly implemented and still experimental. But saturation has been the official semantics for float<->int `as` casts for years now. A flag for turning it off no longer serves any purpose, it's just `-Zplease-miscompile-casts` now. --- src/cast.rs | 4 ---- src/codegen_f16_f128.rs | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/cast.rs b/src/cast.rs index f124739d1e154..abf4326f91888 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -148,10 +148,6 @@ pub(crate) fn clif_int_or_float_cast( fx.bcx.ins().fcvt_to_uint_sat(to_ty, from) }; - if let Some(false) = fx.tcx.sess.opts.unstable_opts.saturating_float_casts { - return val; - } - let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from); let zero = type_zero_value(&mut fx.bcx, to_ty); fx.bcx.ins().select(is_not_nan, val, zero) diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs index 3dbd59c2fca4d..09762f1a451b6 100644 --- a/src/codegen_f16_f128.rs +++ b/src/codegen_f16_f128.rs @@ -265,10 +265,6 @@ pub(crate) fn codegen_cast( fx.bcx.ins().ireduce(to_ty, val) }; - if let Some(false) = fx.tcx.sess.opts.unstable_opts.saturating_float_casts { - return val; - } - let is_not_nan = fcmp(fx, FloatCC::Equal, from, from); let zero = type_zero_value(&mut fx.bcx, to_ty); fx.bcx.ins().select(is_not_nan, val, zero) From ee07e8511f704208269d2dd694e12e65f6cb12bf Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 13 Aug 2026 22:03:50 -0700 Subject: [PATCH 12/28] Add intrinsics for integer minimum and maximum --- src/intrinsics/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 4a779e22870f6..584e4a895be9b 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -630,6 +630,26 @@ fn codegen_regular_intrinsic_call<'tcx>( let res = crate::num::codegen_int_binop(fx, BinOp::Div, x, y); ret.write_cvalue(fx, res); } + // FIXME: remove the guard here once `umin.i128` and friends are supported + // cc https://github.com/bytecodealliance/wasmtime/issues/13790 + sym::integer_max | sym::integer_min if ret.layout().size <= Size::from_bits(64) => { + intrinsic_args!(fx, args => (lhs, rhs); intrinsic); + + assert_eq!(lhs.layout().ty, rhs.layout().ty); + let signed = type_sign(lhs.layout().ty); + let lhs = lhs.load_scalar(fx); + let rhs = rhs.load_scalar(fx); + let res = match (intrinsic, signed) { + (sym::integer_max, false) => fx.bcx.ins().umax(lhs, rhs), + (sym::integer_max, true) => fx.bcx.ins().smax(lhs, rhs), + (sym::integer_min, false) => fx.bcx.ins().umin(lhs, rhs), + (sym::integer_min, true) => fx.bcx.ins().smin(lhs, rhs), + _ => unreachable!(), + }; + + let res = CValue::by_val(res, ret.layout()); + ret.write_cvalue(fx, res); + } sym::saturating_add | sym::saturating_sub => { intrinsic_args!(fx, args => (lhs, rhs); intrinsic); From 0dc10aa50ab71548aa48f4c4d3144d256200e7e9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 6 Aug 2026 19:15:04 +0200 Subject: [PATCH 13/28] attach naked function target features to module assembly --- src/global_asm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/global_asm.rs b/src/global_asm.rs index 9763b0c0fa867..c5b164b8e9cce 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -30,6 +30,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> { operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span], + _extra_rust_target_features: &[String], ) { codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options); } From 52363bd25a9d838c9d8262a24dcc57fac45e025c Mon Sep 17 00:00:00 2001 From: N1ark Date: Wed, 12 Aug 2026 12:01:29 +0100 Subject: [PATCH 14/28] Cleanup cranelift `codegen_float_intrinsic_call` --- src/intrinsics/mod.rs | 45 ++++++++++++------------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 584e4a895be9b..942839942f503 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -448,36 +448,16 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift operations // for `f16` and `f128` once the lowerings have been implemented in Cranelift. - let res = match intrinsic { + let val = match intrinsic { sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { - CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) - } - sym::copysignf32 | sym::copysignf64 => { - CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) - } - sym::floorf32 - | sym::floorf64 - | sym::ceilf32 - | sym::ceilf64 - | sym::truncf32 - | sym::truncf64 - | sym::round_ties_even_f32 - | sym::round_ties_even_f64 - | sym::sqrtf32 - | sym::sqrtf64 => { - let val = match intrinsic { - sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), - sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), - sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), - sym::round_ties_even_f32 | sym::round_ties_even_f64 => { - fx.bcx.ins().nearest(args[0]) - } - sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), - _ => unreachable!(), - }; - - CValue::by_val(val, layout) + fx.bcx.ins().fma(args[0], args[1], args[2]) } + sym::copysignf32 | sym::copysignf64 => fx.bcx.ins().fcopysign(args[0], args[1]), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), + sym::round_ties_even_f32 | sym::round_ties_even_f64 => fx.bcx.ins().nearest(args[0]), + sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), // These intrinsics aren't supported natively by Cranelift. // Lower them to a libcall. @@ -492,20 +472,19 @@ fn codegen_float_intrinsic_call<'tcx>( let input_tys: Vec<_> = vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)]; let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0]; - let ret_val = if intrinsic == sym::powif16 { + if intrinsic == sym::powif16 { codegen_f16_f128::f32_to_f16(fx, ret_val) } else { ret_val - }; - CValue::by_val(ret_val, fx.layout_of(ty)) + } } _ => { let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect(); - let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0]; - CValue::by_val(ret_val, fx.layout_of(ty)) + fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0] } }; + let res = CValue::by_val(val, layout); ret.write_cvalue(fx, res); true From 2bba73bdbeb9b1be9b514865e2e772cfbaf835af Mon Sep 17 00:00:00 2001 From: N1ark Date: Mon, 17 Aug 2026 16:18:46 +0200 Subject: [PATCH 15/28] Make sin, cos, exp, exp2, log, log2, log10 generic --- src/intrinsics/mod.rs | 102 +++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 942839942f503..cf1c1f027e7f5 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -322,16 +322,6 @@ fn codegen_float_intrinsic_call<'tcx>( ret: CPlace<'tcx>, ) -> bool { let (name, arg_count, ty, clif_ty) = match intrinsic { - sym::expf16 => return false, // has a fallback via f32 - sym::expf32 => ("expf", 1, fx.tcx.types.f32, types::F32), - sym::expf64 => ("exp", 1, fx.tcx.types.f64, types::F64), - sym::expf128 => ("expf128", 1, fx.tcx.types.f128, types::F128), - - sym::exp2f16 => return false, // has a fallback via f32 - sym::exp2f32 => ("exp2f", 1, fx.tcx.types.f32, types::F32), - sym::exp2f64 => ("exp2", 1, fx.tcx.types.f64, types::F64), - sym::exp2f128 => ("exp2f128", 1, fx.tcx.types.f128, types::F128), - sym::sqrtf16 => return false, // has a fallback via f32 sym::sqrtf32 => ("sqrtf", 1, fx.tcx.types.f32, types::F32), sym::sqrtf64 => ("sqrt", 1, fx.tcx.types.f64, types::F64), @@ -347,22 +337,7 @@ fn codegen_float_intrinsic_call<'tcx>( sym::powf64 => ("pow", 2, fx.tcx.types.f64, types::F64), sym::powf128 => ("powf128", 2, fx.tcx.types.f128, types::F128), - sym::logf16 => return false, // has a fallback via f32 - sym::logf32 => ("logf", 1, fx.tcx.types.f32, types::F32), - sym::logf64 => ("log", 1, fx.tcx.types.f64, types::F64), - sym::logf128 => ("logf128", 1, fx.tcx.types.f128, types::F128), - - sym::log2f16 => return false, // has a fallback via f32 - sym::log2f32 => ("log2f", 1, fx.tcx.types.f32, types::F32), - sym::log2f64 => ("log2", 1, fx.tcx.types.f64, types::F64), - sym::log2f128 => ("log2f128", 1, fx.tcx.types.f128, types::F128), - - sym::log10f16 => return false, // has a fallback via f32 - sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), - sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), - sym::log10f128 => ("log10f128", 1, fx.tcx.types.f128, types::F128), - - sym::fmaf16 => return false, // has a fallback via f32 + sym::fmaf16 => return false, // has a fallback via f64 sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), sym::fmaf128 => ("fmaf128", 3, fx.tcx.types.f128, types::F128), @@ -404,16 +379,6 @@ fn codegen_float_intrinsic_call<'tcx>( sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), sym::roundf128 => ("roundf128", 1, fx.tcx.types.f128, types::F128), - sym::sinf16 => return false, // has a fallback via f32 - sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), - sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), - sym::sinf128 => ("sinf128", 1, fx.tcx.types.f128, types::F128), - - sym::cosf16 => return false, // has a fallback via f32 - sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), - sym::cosf64 => ("cos", 1, fx.tcx.types.f64, types::F64), - sym::cosf128 => ("cosf128", 1, fx.tcx.types.f128, types::F128), - _ => return false, }; @@ -1198,7 +1163,14 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } - sym::fabs => { + sym::fabs + | sym::exp + | sym::exp2 + | sym::log + | sym::log2 + | sym::log10 + | sym::sin + | sym::cos => { intrinsic_args!(fx, args => (arg); intrinsic); let layout = arg.layout(); let ty::Float(float_ty) = layout.ty.kind() else { @@ -1208,13 +1180,61 @@ fn codegen_regular_intrinsic_call<'tcx>( layout.ty ); }; + enum IntrinsicFallback { + Fallback(&'static str), + Codegen(Value), + } + use FloatTy::*; + use IntrinsicFallback::*; let x = arg.load_scalar(fx); - let val = match float_ty { - FloatTy::F32 | FloatTy::F64 => fx.bcx.ins().fabs(x), + let res = match (intrinsic, float_ty) { + (sym::fabs, F32 | F64) => Codegen(fx.bcx.ins().fabs(x)), // FIXME(bytecodealliance/wasmtime#8312): Use `fabsf16` once Cranelift // backend lowerings are implemented. - FloatTy::F16 => codegen_f16_f128::abs_f16(fx, x), - FloatTy::F128 => codegen_f16_f128::abs_f128(fx, x), + (sym::fabs, F16) => Codegen(codegen_f16_f128::abs_f16(fx, x)), + (sym::fabs, F128) => Codegen(codegen_f16_f128::abs_f128(fx, x)), + + (sym::exp, F32) => Fallback("expf"), + (sym::exp, F64) => Fallback("exp"), + (sym::exp, F128) => Fallback("expf128"), + + (sym::exp2, F32) => Fallback("exp2f"), + (sym::exp2, F64) => Fallback("exp2"), + (sym::exp2, F128) => Fallback("exp2f128"), + + (sym::log, F32) => Fallback("logf"), + (sym::log, F64) => Fallback("log"), + (sym::log, F128) => Fallback("logf128"), + + (sym::log2, F32) => Fallback("log2f"), + (sym::log2, F64) => Fallback("log2"), + (sym::log2, F128) => Fallback("log2f128"), + + (sym::log10, F32) => Fallback("log10f"), + (sym::log10, F64) => Fallback("log10"), + (sym::log10, F128) => Fallback("log10f128"), + + (sym::sin, F32) => Fallback("sinf"), + (sym::sin, F64) => Fallback("sin"), + (sym::sin, F128) => Fallback("sinf128"), + + (sym::cos, F32) => Fallback("cosf"), + (sym::cos, F64) => Fallback("cos"), + (sym::cos, F128) => Fallback("cosf128"), + + (_, F16) => { + // We implement fallbacks for other f16 intrinsics via f32 + return Err(Instance::new_raw(instance.def_id(), instance.args)); + } + + _ => unreachable!(), + }; + let val = match res { + Codegen(val) => val, + Fallback(name) => { + let ty = fx.clif_type(layout.ty).unwrap(); + fx.lib_call(name, vec![AbiParam::new(ty)], vec![AbiParam::new(ty)], &[x])[0] + } }; let val = CValue::by_val(val, layout); ret.write_cvalue(fx, val); From 51dfc2b349ea16ab61e8aec1ad44ed5383d59c21 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Aug 2026 11:35:48 +0200 Subject: [PATCH 16/28] miri: enforce proper types for c-variadic arguments in shims --- .../src/interpret/intrinsics.rs | 72 +++++++++++++++++-- .../rustc_middle/src/mir/interpret/error.rs | 2 +- library/std/src/sys/sync/futex/unix.rs | 6 +- src/tools/miri/src/shims/sig.rs | 61 ++++++++++++---- src/tools/miri/src/shims/unix/fs.rs | 13 ++-- .../miri/src/shims/unix/linux_like/sync.rs | 13 ++-- .../miri/src/shims/unix/linux_like/syscall.rs | 4 +- .../miri/src/shims/unix/linux_like/thread.rs | 4 +- src/tools/miri/src/shims/unix/tcp_socket.rs | 2 +- .../miri/src/shims/unix/virtual_socket.rs | 2 +- .../fs/unix_open_missing_required_mode.rs | 2 +- .../fs/unix_open_missing_required_mode.stderr | 2 +- .../fail-dep/libc/open_wrong_var_arg_type.rs | 18 +++++ .../libc/open_wrong_var_arg_type.stderr | 13 ++++ ...rs => vararg_callee_signature_mismatch.rs} | 2 +- ...> vararg_callee_signature_mismatch.stderr} | 4 +- .../shims/vararg_caller_signature_mismatch.rs | 2 +- .../vararg_caller_signature_mismatch.stderr | 2 +- .../tests/pass-dep/concurrency/linux-futex.rs | 50 ++++++------- 19 files changed, 204 insertions(+), 70 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr rename src/tools/miri/tests/fail/shims/{non_vararg_signature_mismatch.rs => vararg_callee_signature_mismatch.rs} (85%) rename src/tools/miri/tests/fail/shims/{non_vararg_signature_mismatch.stderr => vararg_callee_signature_mismatch.stderr} (74%) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 00057dc503827..e1b690a4f6be9 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -71,6 +71,7 @@ pub enum VarArgCompatible { /// `T` and `U` are definitely not compatible. Incompatible, /// `T` and `U` are corresponding signed and unsigned integer types. + /// This is compatible only if the value can be represented in both types. CastIntTo { source_is_signed: bool }, } @@ -817,7 +818,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// integers of the same size but different signedness, the passed value must be representable /// in both types. fn validate_c_variadic_argument( - &mut self, + &self, arg_mplace: &MPlaceTy<'tcx, M::Provenance>, callee_type: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { @@ -866,8 +867,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// - `T` and `U` are both pointers, and their target types are compatible. /// - `T` is a pointer to [`std::ffi::c_void`] and `U` is a pointer to [`i8`] or [`u8`], /// or vice versa. + /// + /// This is designed to match the C rules for variadics, it is incomparable to what we allow in + /// terms of ABI mismatches for regular (fixed) function arguments. pub fn validate_c_variadic_compatible_ty( - &mut self, + &self, caller_type: Ty<'tcx>, callee_type: Ty<'tcx>, ) -> InterpResult<'tcx, VarArgCompatible> { @@ -884,7 +888,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let is_c_char = |ty: Ty<'_>| matches!(ty.kind(), ty::Uint(UintTy::U8) | ty::Int(IntTy::I8)); match (caller_type.kind(), callee_type.kind()) { - (ty::RawPtr(caller_target_ty, _), ty::RawPtr(callee_target_ty, _)) => { + // Some types look different but are actually the same for ABI purposes. + (ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => { + // E.g. cast between `usize` and `u64` on a 64-bit platform. + interp_ok(VarArgCompatible::Compatible) + } + // C allows different types if... + // - "both types are pointers to qualified or unqualified versions of compatible types" + // - "one type is pointer to qualified or unqualified void and the other is a pointer to a qualified or + // unqualified character type" + // + // As usual for the ABI, we treat references and raw pointers alike. + ( + ty::RawPtr(caller_target_ty, _) | ty::Ref(_, caller_target_ty, _), + ty::RawPtr(callee_target_ty, _) | ty::Ref(_, callee_target_ty, _), + ) => { // In C, types can be qualified by a combination of `const`, `volatile` and // `restrict`. These properties are irrelevant for the ABI, and don't have an // equivalent in rust. @@ -910,16 +928,58 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } } + // - "one type is a signed integer type, the other type is the corresponding unsigned integer type, + // and the value is representable in both types" (ty::Int(_), ty::Uint(_)) => { interp_ok(VarArgCompatible::CastIntTo { source_is_signed: true }) } (ty::Uint(_), ty::Int(_)) => { interp_ok(VarArgCompatible::CastIntTo { source_is_signed: false }) } - (ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => { - // E.g. cast between `usize` and `u64` on a 64-bit platform. - interp_ok(VarArgCompatible::Compatible) + // - "or, the type of the next argument is nullptr_t and type is a pointer type that has the same + // representation and alignment requirements as a pointer to a character type" + // This one does not have an equivalent form in Rust. + + // C also considers two structs to be the same if they have the same name and the same + // fields. We need a similar rules that that e.g. if caller and callee use the "same" + // type from two different versions of the same crate, that call is accepted. + (ty::Adt(caller_adt, caller_args), ty::Adt(callee_adt, callee_args)) + if (caller_adt.is_struct() && callee_adt.is_struct()) + && (caller_adt.repr().c() && callee_adt.repr().c()) + && (self.tcx.item_name(caller_adt.did()) + == self.tcx.item_name(callee_adt.did())) => + { + let caller_fields = &caller_adt.non_enum_variant().fields; + let callee_fields = &callee_adt.non_enum_variant().fields; + if caller_fields.len() == callee_fields.len() + && caller_fields.iter().zip(callee_fields).try_fold( + true, + |acc, (caller_field, callee_field)| { + if !acc { + return interp_ok(false); + } + if caller_field.name != callee_field.name { + return interp_ok(false); + } + let caller_ty = caller_field.ty(*self.tcx, caller_args); + let caller_ty = + self.tcx.normalize_erasing_regions(self.typing_env, caller_ty); + let callee_ty = callee_field.ty(*self.tcx, callee_args); + let callee_ty = + self.tcx.normalize_erasing_regions(self.typing_env, callee_ty); + interp_ok(matches!( + self.validate_c_variadic_compatible_ty(caller_ty, callee_ty)?, + VarArgCompatible::Compatible + )) + }, + )? + { + interp_ok(VarArgCompatible::Compatible) + } else { + interp_ok(VarArgCompatible::Incompatible) + } } + _ => interp_ok(VarArgCompatible::Incompatible), } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index fb82f694d6f74..049e1ec22e547 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -418,7 +418,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> }, /// ABI-incompatible argument types. AbiMismatchArgument { - /// The index of the argument whose type is wrong. + /// The index of the argument whose type is wrong (starting at index 0). arg_idx: usize, caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx>, diff --git a/library/std/src/sys/sync/futex/unix.rs b/library/std/src/sys/sync/futex/unix.rs index 9291860d4934c..004d8323060e5 100644 --- a/library/std/src/sys/sync/futex/unix.rs +++ b/library/std/src/sys/sync/futex/unix.rs @@ -62,7 +62,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) // absolute time rather than a relative time. libc::syscall( libc::SYS_futex, - futex as *const Atomic, + futex as *const Atomic as *const u32, libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, expected, timespec.as_ref().map_or(null(), |t| t as *const libc::timespec), @@ -92,7 +92,7 @@ pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) /// On some platforms, this always returns false. #[cfg(any(target_os = "linux", target_os = "android"))] pub fn futex_wake(futex: &Atomic) -> bool { - let ptr = futex as *const Atomic; + let ptr = futex as *const Atomic as *const u32; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, op, 1) > 0 } } @@ -100,7 +100,7 @@ pub fn futex_wake(futex: &Atomic) -> bool { /// Wakes up all threads that are waiting on `futex_wait` on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] pub fn futex_wake_all(futex: &Atomic) { - let ptr = futex as *const Atomic; + let ptr = futex as *const Atomic as *const u32; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, op, i32::MAX); diff --git a/src/tools/miri/src/shims/sig.rs b/src/tools/miri/src/shims/sig.rs index a5da61d633606..e2e01d8ba0aa7 100644 --- a/src/tools/miri/src/shims/sig.rs +++ b/src/tools/miri/src/shims/sig.rs @@ -150,9 +150,19 @@ macro_rules! shim_sig_arg { $this.tcx.types.bool }; ($this:ident, *_) => { + // Pointee types usually don't matter so we allow it to be omitted. // Mutability does not matter for ABI. $this.machine.layouts.mut_raw_ptr.ty }; + ($this:ident, *$($ty:tt)*) => { + // Pointee types matter for varargs so we support explicitly giving them. + // Mutability does not matter for ABI. + rustc_middle::ty::Ty::new_ptr( + *$this.tcx, + shim_sig_arg!($this, $($ty)*), + rustc_middle::mir::Mutability::Mut, + ) + }; ($this:ident, fn(..) -> _) => { // We currently treat fn ptrs as ABI-compatible with data ptrs so we can just use a raw ptr. $this.machine.layouts.const_raw_ptr.ty @@ -208,12 +218,12 @@ fn check_shim_abi<'tcx>( if caller_abi.c_variadic && !callee_abi.c_variadic { throw_ub_format!( - "ABI mismatch: `{link_name}` is a non-variadic function, but the caller is using a variadic signature" + "ABI mismatch: `{link_name}` is a non-variadic function, but the caller is using a c-variadic signature" ); } if !caller_abi.c_variadic && callee_abi.c_variadic { throw_ub_format!( - "ABI mismatch: `{link_name}` is a variadic function, but the caller is using a non-variadic signature" + "ABI mismatch: `{link_name}` is a c-variadic function, but the caller is using a non-variadic signature" ); } @@ -254,7 +264,7 @@ fn check_shim_abi<'tcx>( // Deliberately not `Copy` so that we don't consume the same vararg multiple times accidentally. pub struct Varargs<'tcx, 'a> { args: &'a [OpTy<'tcx>], - /// Number of variadic arguments that have already been taken, for error messages. + /// Number of arguments (variadic and fixed) that have already been taken, for error messages. already_gone: usize, } @@ -299,7 +309,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } if abi.c_variadic { throw_ub_format!( - "calling a non-variadic function with a variadic caller-side signature" + "calling a non-variadic function with a c-variadic caller-side signature" ); } @@ -360,7 +370,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Return arguments. if let Some((fixed, var)) = caller_args.split_first_chunk() { - return interp_ok((fixed, Varargs { args: var, already_gone: 0 })); + return interp_ok((fixed, Varargs { args: var, already_gone: N })); } unreachable!() } @@ -378,20 +388,45 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Some((now, tail)) = varargs.args.split_first_chunk::() else { throw_ub_format!( - "not enough variadic arguments for `{fn_name}`: got {}, expected at least {}", + "not enough arguments for `{fn_name}`: got {}, expected at least {}", varargs.already_gone.strict_add(varargs.args.len()), varargs.already_gone.strict_add(N), ) }; for (n, (caller_gave, callee_expected)) in now.iter().zip(tys).enumerate() { - // Check ABI compatibility. This is less strict than `next_arg` but we're also - // not limited to just a few simple types. - let callee_expected = this.layout_of(callee_expected)?; - - // FIXME: check compatibility once - // landed. - let _unused = (n, caller_gave, callee_expected); + // Check ABI compatibility. + let compatible = + this.validate_c_variadic_compatible_ty(caller_gave.layout.ty, callee_expected)?; + match compatible { + VarArgCompatible::Compatible => {} + VarArgCompatible::Incompatible => { + throw_ub_format!( + "incorrect c-variadic argument type for `{fn_name}`: \ + expected argument #{n} to have type `{callee_expected}` but got incompatible type `{caller_ty}`", + n = varargs.already_gone.strict_add(n).strict_add(1), + caller_ty = caller_gave.layout.ty, + ); + } + VarArgCompatible::CastIntTo { source_is_signed } => { + // Check that the value can be represented in the target type. + let size = caller_gave.layout.size; + let scalar = this.read_scalar(caller_gave)?; + if scalar.to_int(size)? < 0 { + throw_ub_format!( + "incorrect c-variadic argument type for `{fn_name}`: \ + argument #{n} has value `{value}_{caller_ty}` which cannot be represented in expected type `{callee_expected}`", + n = varargs.already_gone.strict_add(n).strict_add(1), + caller_ty = caller_gave.layout.ty, + value = if source_is_signed { + scalar.to_int(size)?.to_string() + } else { + scalar.to_uint(size)?.to_string() + } + ) + } + } + } } interp_ok((now, Varargs { args: tail, already_gone: varargs.already_gone.strict_add(N) })) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 427fec0c84405..1ad71d0d8a648 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -460,11 +460,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let o_creat = this.eval_libc_i32("O_CREAT"); if flag & o_creat == o_creat { flag &= !o_creat; - // Get the mode. On macOS, the argument type `mode_t` is actually `u16`, but - // C integer promotion rules mean that on the ABI level, it gets passed as `u32` - // (see https://github.com/rust-lang/rust/issues/71915). + // Get the mode. let ([mode], _) = this.check_varargs( - shim_varargs![libc::mode_t], + if this.libc_ty_layout("mode_t").size.bytes() >= 4 { + // `mode_t` is big enough, no C integer promotion. + shim_varargs![libc::mode_t] + } else { + // Types smaller than int get promoted to int + // (see https://github.com/rust-lang/rust/issues/71915). + shim_varargs![i32] + }, varargs, "open(pathname, O_CREAT, ...)", )?; diff --git a/src/tools/miri/src/shims/unix/linux_like/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs index ebbaa836007aa..12a4a1b252ad7 100644 --- a/src/tools/miri/src/shims/unix/linux_like/sync.rs +++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs @@ -16,7 +16,7 @@ pub fn futex<'tcx>( dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let ([addr, op, val], varargs) = - ecx.check_varargs(shim_varargs![*_, i32, u32], varargs, "syscall(SYS_futex, ...)")?; + ecx.check_varargs(shim_varargs![*u32, i32, u32], varargs, "syscall(SYS_futex, ...)")?; // See for docs. // The first three arguments (after the syscall number itself) are the same to all futex operations: @@ -52,7 +52,7 @@ pub fn futex<'tcx>( let (timeout, bitset) = if wait_bitset { let ([timeout, uaddr2, bitset], _) = ecx.check_varargs( - shim_varargs![*_, *_, u32], + shim_varargs![*libc::timespec, *u32, u32], varargs, "syscall(SYS_futex, ...)", )?; @@ -62,8 +62,11 @@ pub fn futex<'tcx>( } (timeout, ecx.read_scalar(bitset)?.to_u32()?) } else { - let ([timeout], _) = - ecx.check_varargs(shim_varargs![*_], varargs, "syscall(SYS_futex, ...)")?; + let ([timeout], _) = ecx.check_varargs( + shim_varargs![*libc::timespec], + varargs, + "syscall(SYS_futex, ...)", + )?; (timeout, u32::MAX) }; @@ -199,7 +202,7 @@ pub fn futex<'tcx>( let bitset = if op == futex_wake_bitset { let ([timeout, uaddr2, bitset], _) = ecx.check_varargs( - shim_varargs![*_, *_, u32], + shim_varargs![*libc::timespec, *u32, u32], varargs, "syscall(SYS_futex, ...)", )?; diff --git a/src/tools/miri/src/shims/unix/linux_like/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs index ae9b332657463..2260a0342e7e2 100644 --- a/src/tools/miri/src/shims/unix/linux_like/syscall.rs +++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs @@ -37,7 +37,7 @@ pub fn syscall<'tcx>( // Used by getrandom 0.1 // The first argument is the syscall id, so skip over it. let ([ptr, len, flags], _) = ecx.check_varargs( - shim_varargs![*_, usize, i32], + shim_varargs![*libc::c_void, usize, i32], varargs, "syscall(SYS_getrandom, ...)", )?; @@ -70,7 +70,7 @@ pub fn syscall<'tcx>( num if num == sys_accept4 => { // Used on Android. let ([socket, address, address_len, flags], _) = ecx.check_varargs( - shim_varargs![i32, *_, *_, i32], + shim_varargs![i32, *libc::sockaddr, *libc::socklen_t, i32], varargs, "syscall(SYS_accept4, ...)", )?; diff --git a/src/tools/miri/src/shims/unix/linux_like/thread.rs b/src/tools/miri/src/shims/unix/linux_like/thread.rs index 8ddf122af654f..987de85740ea5 100644 --- a/src/tools/miri/src/shims/unix/linux_like/thread.rs +++ b/src/tools/miri/src/shims/unix/linux_like/thread.rs @@ -26,7 +26,7 @@ pub fn prctl<'tcx>( let res = match ecx.read_scalar(op)?.to_i32()? { op if op == pr_set_name => { let ([name], _) = - ecx.check_varargs(shim_varargs![*_], varargs, "prctl(PR_SET_NAME, ...)")?; + ecx.check_varargs(shim_varargs![*libc::c_char], varargs, "prctl(PR_SET_NAME, ...)")?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; @@ -39,7 +39,7 @@ pub fn prctl<'tcx>( } op if op == pr_get_name => { let ([name], _) = - ecx.check_varargs(shim_varargs![*_], varargs, "prctl(PR_GET_NAME, ...)")?; + ecx.check_varargs(shim_varargs![*libc::c_char], varargs, "prctl(PR_GET_NAME, ...)")?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; diff --git a/src/tools/miri/src/shims/unix/tcp_socket.rs b/src/tools/miri/src/shims/unix/tcp_socket.rs index d0966fab8ab92..d9cc802cd4469 100644 --- a/src/tools/miri/src/shims/unix/tcp_socket.rs +++ b/src/tools/miri/src/shims/unix/tcp_socket.rs @@ -208,7 +208,7 @@ impl UnixFileDescription for TcpSocket { ); } - let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*_], args, "ioctl")?; + let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*i32], args, "ioctl")?; let value = ecx.deref_pointer_as(value_ptr, ecx.machine.layouts.i32)?; let non_block = ecx.read_scalar(&value)?.to_i32()? != 0; self.is_non_block.set(non_block); diff --git a/src/tools/miri/src/shims/unix/virtual_socket.rs b/src/tools/miri/src/shims/unix/virtual_socket.rs index a035b56c1e323..04bc2ab8a890a 100644 --- a/src/tools/miri/src/shims/unix/virtual_socket.rs +++ b/src/tools/miri/src/shims/unix/virtual_socket.rs @@ -291,7 +291,7 @@ impl UnixFileDescription for VirtualSocket { ); } - let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*_], args, "ioctl")?; + let ([value_ptr], _) = ecx.check_varargs(shim_varargs![*i32], args, "ioctl")?; let value = ecx.deref_pointer_as(value_ptr, ecx.machine.layouts.i32)?; let non_block = ecx.read_scalar(&value)?.to_i32()? != 0; self.is_nonblock.set(non_block); diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs index 29548c17443a6..2283d3308b935 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs @@ -7,5 +7,5 @@ fn main() { fn test_file_open_missing_needed_mode() { let name = c"missing_arg.txt".as_ptr(); - let _fd = unsafe { libc::open(name, libc::O_CREAT) }; //~ ERROR: Undefined Behavior: not enough variadic arguments + let _fd = unsafe { libc::open(name, libc::O_CREAT) }; //~ ERROR: /Undefined Behavior: not enough arguments.*: got 2/ } diff --git a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr index 186ca4ccdd406..0ef9d10461127 100644 --- a/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr +++ b/src/tools/miri/tests/fail-dep/libc/fs/unix_open_missing_required_mode.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: not enough variadic arguments for `open(pathname, O_CREAT, ...)`: got 0, expected at least 1 +error: Undefined Behavior: not enough arguments for `open(pathname, O_CREAT, ...)`: got 2, expected at least 3 --> tests/fail-dep/libc/fs/unix_open_missing_required_mode.rs:LL:CC | LL | let _fd = unsafe { libc::open(name, libc::O_CREAT) }; diff --git a/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs new file mode 100644 index 0000000000000..3382670b50f18 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs @@ -0,0 +1,18 @@ +//@ignore-target: windows # File handling is not implemented yet +//@compile-flags: -Zmiri-disable-isolation +//@normalize-stderr-test: "to have type `(u32|i32)`" -> "to have type `$$TYPE`" + +#![allow(invalid_runtime_symbol_definitions)] + +use std::ffi::{CString, OsStr}; +use std::os::unix::ffi::OsStrExt; + +use libc::open; + +fn main() { + let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let _fd = unsafe { + open(c_path.as_ptr(), libc::O_CREAT, /* should be mode_t */ 0u64) + //~^ ERROR: /expected argument #3 to have type `(u32|i32)` but got incompatible type `u64`/ + }; +} diff --git a/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr new file mode 100644 index 0000000000000..8008844273fd7 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: incorrect c-variadic argument type for `open(pathname, O_CREAT, ...)`: expected argument #3 to have type `$TYPE` but got incompatible type `u64` + --> tests/fail-dep/libc/open_wrong_var_arg_type.rs:LL:CC + | +LL | open(c_path.as_ptr(), libc::O_CREAT, /* should be mode_t */ 0u64) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs similarity index 85% rename from src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs rename to src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs index bf3d4174dbdb7..ce0c6c289faf0 100644 --- a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs @@ -15,6 +15,6 @@ fn main() { let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); let _fd = unsafe { open(c_path.as_ptr(), /* value does not matter */ 0) - //~^ ERROR: is a variadic function, but the caller is using a non-variadic signature + //~^ ERROR: is a c-variadic function, but the caller is using a non-variadic signature }; } diff --git a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.stderr similarity index 74% rename from src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr rename to src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.stderr index 788b499841174..be65cd0068d1f 100644 --- a/src/tools/miri/tests/fail/shims/non_vararg_signature_mismatch.stderr +++ b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.stderr @@ -1,5 +1,5 @@ -error: Undefined Behavior: ABI mismatch: `open` is a variadic function, but the caller is using a non-variadic signature - --> tests/fail/shims/non_vararg_signature_mismatch.rs:LL:CC +error: Undefined Behavior: ABI mismatch: `open` is a c-variadic function, but the caller is using a non-variadic signature + --> tests/fail/shims/vararg_callee_signature_mismatch.rs:LL:CC | LL | open(c_path.as_ptr(), /* value does not matter */ 0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs index 1dc36706e284b..be5f44d988430 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs @@ -9,6 +9,6 @@ extern "C" { fn main() { let mut fds = [-1, -1]; let res = unsafe { pipe(fds.as_mut_ptr()) }; - //~^ ERROR: is a non-variadic function, but the caller is using a variadic signature + //~^ ERROR: is a non-variadic function, but the caller is using a c-variadic signature assert_eq!(res, 0); } diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr index 0405fe0ef7501..98fccde50be13 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: ABI mismatch: `pipe` is a non-variadic function, but the caller is using a variadic signature +error: Undefined Behavior: ABI mismatch: `pipe` is a non-variadic function, but the caller is using a c-variadic signature --> tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC | LL | let res = unsafe { pipe(fds.as_mut_ptr()) }; diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index 2e45af9e28880..9df436a5b6604 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -42,7 +42,7 @@ fn wake_nobody() { fn wake_dangling() { let futex = Box::new(0); - let ptr: *const i32 = &*futex; + let ptr: *const u32 = &*futex; drop(futex); // Expect error since this is now "unmapped" memory. @@ -55,7 +55,7 @@ fn wake_dangling() { } fn wait_wrong_val() { - let futex: i32 = 123; + let futex: u32 = 123; // Only wait if the futex value is 456. unsafe { @@ -76,7 +76,7 @@ fn wait_wrong_val() { fn wait_timeout() { let start = Instant::now(); - let futex: i32 = 123; + let futex: u32 = 123; // Wait for 100ms, with nobody waking us up early. unsafe { @@ -120,12 +120,12 @@ fn wait_absolute_timeout() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAIT_BITSET, - 123, + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAIT_BITSET, // op + 123, // val &timeout, - 0usize, - u32::MAX, + ptr::null::(), // uaddr2 + u32::MAX, // val3 (bitset) ), -1, ); @@ -181,12 +181,12 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAKE_BITSET, - 10, // Wake up at most 10 threads. + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAKE_BITSET, // op + 10, // val (max wake up count) ptr::null::(), - 0usize, - 0b1001, // bitset + ptr::null::(), // uaddr2 + 0b1001, // val3 (bitset) ), 0, // Didn't match any thread. ); @@ -196,12 +196,12 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAKE_BITSET, - 10, // Wake up at most 10 threads. + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAKE_BITSET, // op + 10, // val (max wake up count) ptr::null::(), - 0usize, - 0b0110, // bitset + ptr::null::(), // uaddr2 + 0b0110, // val3 (bitset) ), 1, // Woken up one thread. ); @@ -214,12 +214,12 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), - libc::FUTEX_WAIT_BITSET, - 0, + addr_of!(FUTEX), // uaddr + libc::FUTEX_WAIT_BITSET, // op + 0, // val ptr::null::(), - 0usize, - 0b0100, // bitset + ptr::null::(), // uaddr2 + 0b0100, // val3 (bitset) ), 0, ); @@ -255,7 +255,7 @@ fn concurrent_wait_wake() { unsafe { let ret = libc::syscall( libc::SYS_futex, - addr_of!(FUTEX), + addr_of!(FUTEX).cast::(), libc::FUTEX_WAIT, HELD, ptr::null::(), @@ -277,7 +277,7 @@ fn concurrent_wait_wake() { FUTEX.store(FREE, Ordering::Relaxed); unsafe { DATA = 1; - libc::syscall(libc::SYS_futex, addr_of!(FUTEX), libc::FUTEX_WAKE, 1); + libc::syscall(libc::SYS_futex, addr_of!(FUTEX).cast::(), libc::FUTEX_WAKE, 1); } t.join().unwrap(); From 158f6f9da42accbe5e15f23fa178b2b7b9b37da7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Aug 2026 12:27:48 +0200 Subject: [PATCH 17/28] share identical-c-type logic with regular ABI checks --- compiler/rustc_abi/src/lib.rs | 10 ++++ .../rustc_const_eval/src/interpret/call.rs | 51 ++++++++++++++++-- .../src/interpret/intrinsics.rs | 52 ++----------------- .../function_calls/not_the_same_c_type.rs | 23 ++++++++ .../function_calls/not_the_same_c_type.stderr | 20 +++++++ .../pass/function_calls/exported_symbol.rs | 21 ++++++++ 6 files changed, 127 insertions(+), 50 deletions(-) create mode 100644 src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs create mode 100644 src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 7cfb93ca1b86d..0e888ea5e42a5 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -245,6 +245,16 @@ impl ReprOptions { pub fn inhibits_union_abi_opt(&self) -> bool { self.c() } + + /// Ensures two `repr` are equal up to the seed. + pub fn equal_up_to_seed(&self, other: &Self) -> bool { + let ReprOptions { int, align, pack, flags, scalable, field_shuffle_seed: _ } = *self; + int == other.int + && align == other.align + && pack == other.pack + && flags == other.flags + && scalable == other.scalable + } } /// The maximum supported number of lanes in a SIMD vector. diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 805c20755d9f7..09d94fdac0260 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -9,7 +9,7 @@ use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_hir::def_id::DefId; use rustc_hir::find_attr; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; -use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; +use rustc_middle::ty::{self, AdtDef, FieldDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::callconv::{ArgAbi, FnAbi}; use tracing::field::Empty; @@ -229,6 +229,48 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) } + /// Determine whether the given types are identical types from the perspective of C. + pub(super) fn identical_c_types(&self, caller_type: Ty<'tcx>, callee_type: Ty<'tcx>) -> bool { + if caller_type == callee_type { + return true; + } + + // C considers two structs to be the same if they have the same name and the same + // fields. We need a similar rules that that e.g. if caller and callee use the "same" + // type from two different versions of the same crate, that call is accepted. + let ty::Adt(caller_adt, caller_args) = caller_type.kind() else { return false }; + let ty::Adt(callee_adt, callee_args) = callee_type.kind() else { return false }; + + if !( + // They must both be structs. + (caller_adt.is_struct() && callee_adt.is_struct()) + // They must have equal `repr`, and it must be `repr(C)`. + && (caller_adt.repr().c() && caller_adt.repr().equal_up_to_seed(&callee_adt.repr())) + // They must have the same name. + && self.tcx.item_name(caller_adt.did()) == self.tcx.item_name(callee_adt.did()) + ) { + return false; + } + + // All fields must have the same names and types as well, where "same type" recursively + // uses this check. + let caller_fields = &caller_adt.non_enum_variant().fields; + let callee_fields = &callee_adt.non_enum_variant().fields; + caller_fields.len() == callee_fields.len() + && caller_fields.iter().zip(callee_fields).all(|(caller_field, callee_field)| { + if caller_field.name != callee_field.name { + return false; // Bail on different name. + } + // Ensure the normalized type is the same. + let normalized_field_ty = |field: &FieldDef, args| { + self.tcx.normalize_erasing_regions(self.typing_env, field.ty(*self.tcx, args)) + }; + let caller_ty = normalized_field_ty(caller_field, caller_args); + let callee_ty = normalized_field_ty(callee_field, callee_args); + self.identical_c_types(caller_ty, callee_ty) + }) + } + /// Check if these two layouts look like they are fn-ABI-compatible. /// (We also compare the `PassMode`, so this doesn't have to check everything. But it turns out /// that only checking the `PassMode` is insufficient.) @@ -252,8 +294,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; let caller = unfold(caller)?; let callee = unfold(callee)?; - // Not-quite-so-fast path: if the types are equal now, they are compatible. - if caller.ty == callee.ty { + // Not-quite-so-fast path: if the types are c-equal now, they are compatible. + // FIXME: This is *not* currently guaranteed by our ABI compatibility docs, but it is needed + // for Miri itself when it checks whether shims were called with the right arguments. + // We should eventually put this into the docs as well. + if self.identical_c_types(caller.ty, callee.ty) { return interp_ok(true); } // Now see if these inner types are compatible. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e1b690a4f6be9..ee1422b257566 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -825,11 +825,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let callee_ty = callee_type.ty; let caller_ty = arg_mplace.layout.ty; - // Identical types are clearly compatible. - if caller_ty == callee_ty { - return interp_ok(()); - } - match self.validate_c_variadic_compatible_ty(arg_mplace.layout.ty, callee_type.ty)? { VarArgCompatible::Compatible => interp_ok(()), VarArgCompatible::Incompatible => throw_ub_format!( @@ -875,7 +870,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { caller_type: Ty<'tcx>, callee_type: Ty<'tcx>, ) -> InterpResult<'tcx, VarArgCompatible> { - if caller_type == callee_type { + // FIXME: Accepting two copies of the same repr(C) type as compatible is currently not + // guaranteed by our `VaList::next_arg` docs, but it is needed for Miri itself when it + // checks whether shims were called with the right arguments. We should eventually put this + // into the docs as well. + if self.identical_c_types(caller_type, callee_type) { return interp_ok(VarArgCompatible::Compatible); } @@ -939,47 +938,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // - "or, the type of the next argument is nullptr_t and type is a pointer type that has the same // representation and alignment requirements as a pointer to a character type" // This one does not have an equivalent form in Rust. - - // C also considers two structs to be the same if they have the same name and the same - // fields. We need a similar rules that that e.g. if caller and callee use the "same" - // type from two different versions of the same crate, that call is accepted. - (ty::Adt(caller_adt, caller_args), ty::Adt(callee_adt, callee_args)) - if (caller_adt.is_struct() && callee_adt.is_struct()) - && (caller_adt.repr().c() && callee_adt.repr().c()) - && (self.tcx.item_name(caller_adt.did()) - == self.tcx.item_name(callee_adt.did())) => - { - let caller_fields = &caller_adt.non_enum_variant().fields; - let callee_fields = &callee_adt.non_enum_variant().fields; - if caller_fields.len() == callee_fields.len() - && caller_fields.iter().zip(callee_fields).try_fold( - true, - |acc, (caller_field, callee_field)| { - if !acc { - return interp_ok(false); - } - if caller_field.name != callee_field.name { - return interp_ok(false); - } - let caller_ty = caller_field.ty(*self.tcx, caller_args); - let caller_ty = - self.tcx.normalize_erasing_regions(self.typing_env, caller_ty); - let callee_ty = callee_field.ty(*self.tcx, callee_args); - let callee_ty = - self.tcx.normalize_erasing_regions(self.typing_env, callee_ty); - interp_ok(matches!( - self.validate_c_variadic_compatible_ty(caller_ty, callee_ty)?, - VarArgCompatible::Compatible - )) - }, - )? - { - interp_ok(VarArgCompatible::Compatible) - } else { - interp_ok(VarArgCompatible::Incompatible) - } - } - _ => interp_ok(VarArgCompatible::Incompatible), } } diff --git a/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs new file mode 100644 index 0000000000000..f3a2e64fced5c --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.rs @@ -0,0 +1,23 @@ +mod somewhere_else { + #[repr(C)] + struct CType { + field: i32, + } + + #[unsafe(no_mangle)] + extern "C" fn work_with_c_type(_x: CType) {} + //~^ERROR: parameter #1 has type somewhere_else::CType passing argument of type CType +} + +// Imagine we import the function from above but we end up with a copy of the type declaration. +// We only accept this if the types are *exactly* the name, including the names of all fields. +#[repr(C)] +struct CType(i32); + +extern "C" { + fn work_with_c_type(_x: CType); +} + +fn main() { + unsafe { work_with_c_type(CType(0)) }; +} diff --git a/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr new file mode 100644 index 0000000000000..6d240c1601021 --- /dev/null +++ b/src/tools/miri/tests/fail/function_calls/not_the_same_c_type.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: calling a function whose parameter #1 has type somewhere_else::CType passing argument of type CType + --> tests/fail/function_calls/not_the_same_c_type.rs:LL:CC + | +LL | extern "C" fn work_with_c_type(_x: CType) {} + | ^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets + = help: if you think this code should be accepted anyway, please report an issue with Miri + = note: stack backtrace: + 0: somewhere_else::work_with_c_type + at tests/fail/function_calls/not_the_same_c_type.rs:LL:CC + 1: main + at tests/fail/function_calls/not_the_same_c_type.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs index d804f3642b1d2..0d764c094d594 100644 --- a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs +++ b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs @@ -24,6 +24,25 @@ impl AssocFn { } } +mod somewhere_else { + #[repr(C)] + struct CType { + field: i32, + } + + #[unsafe(no_mangle)] + extern "C" fn work_with_c_type(_x: CType) {} +} + +// Imagine we import the function from above but we end up with a copy of the type declaration. +#[repr(C)] +struct CType { + field: i32, +} +extern "C" { + fn work_with_c_type(_x: CType); +} + fn main() { // Repeat calls to make sure the `Instance` cache is not broken. for _ in 0..3 { @@ -77,5 +96,7 @@ fn main() { assert_eq!(transmute(qux)(), -4); } } + + unsafe { work_with_c_type(CType { field: 0 }) }; } } From 82e12d618d3d3117293da4be1207ccce34772771 Mon Sep 17 00:00:00 2001 From: Reuben Cruise Date: Mon, 15 Jun 2026 16:26:37 +0100 Subject: [PATCH 18/28] Creates new `InlineAsmSize` enum Facilitates scalable vector support in inline assembly. --- src/inline_asm.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index d4d64cb3fbaf2..cd2b06cc1defb 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -443,11 +443,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .supported_types(self.arch, true) .iter() .map(|(ty, _)| ty.size()) + .filter_map(InlineAsmSize::fixed_size_bytes) .max() - .unwrap(); - let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); + .expect("expected fixed-size type"); + let align = rustc_abi::Align::from_bytes(reg_size).unwrap(); let offset = slot_size.align_to(align); - *slot_size = offset + reg_size; + *slot_size = offset + rustc_abi::Size::from_bytes(reg_size); offset }; let mut new_slot = |x| new_slot_fn(&mut slot_size, x); From 98d4b613fdd547a248e6e2fb0f5abbed866d56d4 Mon Sep 17 00:00:00 2001 From: Matyas Susits Date: Thu, 30 Jul 2026 08:11:34 +0200 Subject: [PATCH 19/28] Disable inline asm line info cookies when llvm bitcode is saved or LTO is enabled The parallel frontend makes the cookies nondeterministic in their current form, resulting in nondeterministic outputs when bitcode is emitted or LTO is used. Causes minor diagnostic regression for inline asm in release builds. --- src/driver/aot.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d6c25cf524a5c..e06549090226e 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -284,6 +284,7 @@ impl ExtraBackendMethods for AotDriver { &self, tcx: TyCtxt<'_>, cgu_name: Symbol, + _bitcode_needed: bool, ) -> (ModuleCodegen, u64) { let start_time = Instant::now(); From 18dd4a87c304bdb7cf53a821512fed7e0ab1fea0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Sep 2026 12:19:36 +0200 Subject: [PATCH 20/28] Reduce size of 0027-stdlib-128bit-atomic-operations.patch --- ...0027-stdlib-128bit-atomic-operations.patch | 81 ++++++------------- 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/patches/0027-stdlib-128bit-atomic-operations.patch b/patches/0027-stdlib-128bit-atomic-operations.patch index 2268ff9cb266e..f821099e68f88 100644 --- a/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/patches/0027-stdlib-128bit-atomic-operations.patch @@ -5,83 +5,54 @@ Subject: [PATCH] Disable 128bit atomic operations Cranelift doesn't support them yet --- - library/core/src/panic/unwind_safe.rs | 6 ----- - library/core/src/sync/atomic.rs | 38 --------------------------- - 2 files changed, 44 deletions(-) + library/core/src/panic/unwind_safe.rs | 4 ++-- + library/core/src/sync/atomic.rs | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs -index a60f0799c0e..af056fbf41f 100644 +index bf2e61d..cb82b07 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs -@@ -216,9 +216,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} +@@ -217,7 +217,7 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} #[cfg(target_has_atomic_load_store = "64")] #[stable(feature = "integer_atomics_stable", since = "1.34.0")] impl RefUnwindSafe for crate::sync::atomic::AtomicI64 {} -#[cfg(target_has_atomic_load_store = "128")] --#[unstable(feature = "integer_atomics", issue = "99069")] --impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} ++#[cfg(false)] + #[unstable(feature = "integer_atomics", issue = "99069")] + impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} - #[cfg(target_has_atomic_load_store = "ptr")] - #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] -@@ -235,9 +232,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} +@@ -236,7 +236,7 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} #[cfg(target_has_atomic_load_store = "64")] #[stable(feature = "integer_atomics_stable", since = "1.34.0")] impl RefUnwindSafe for crate::sync::atomic::AtomicU64 {} -#[cfg(target_has_atomic_load_store = "128")] --#[unstable(feature = "integer_atomics", issue = "99069")] --impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} ++#[cfg(false)] + #[unstable(feature = "integer_atomics", issue = "99069")] + impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} - #[cfg(target_has_atomic_load_store = "8")] - #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index 8a9a0b5..92ed9a6 100644 +index e676a38..b6a9a3c 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -3762,44 +3757,6 @@ atomic_int! { +@@ -3850,7 +3850,7 @@ atomic_int! { 8, u64 AtomicU64 } -#[cfg(any(target_has_atomic_load_store = "128", doc))] --atomic_int! { -- target_has_atomic_load_store = "128", -- target_has_atomic = "128", -- target_has_atomic_primitive_alignment = "128", -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- "i128", -- "#![feature(integer_atomics)]\n\n", -- atomic_min, atomic_max, -- 16, -- i128 AtomicI128 --} ++#[cfg(false)] + atomic_int! { + target_has_atomic_load_store = "128", + target_has_atomic = "128", +@@ -3869,7 +3869,7 @@ atomic_int! { + 16, + i128 AtomicI128 + } -#[cfg(any(target_has_atomic_load_store = "128", doc))] --atomic_int! { -- target_has_atomic_load_store = "128", -- target_has_atomic = "128", -- target_has_atomic_primitive_alignment = "128", -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- "u128", -- "#![feature(integer_atomics)]\n\n", -- atomic_umin, atomic_umax, -- 16, -- u128 AtomicU128 --} - - #[cfg(target_has_atomic_load_store = "ptr")] - macro_rules! atomic_int_ptr_sized { ++#[cfg(false)] + atomic_int! { + target_has_atomic_load_store = "128", + target_has_atomic = "128", -- 2.48.1 From ea847bb0d493dc4a6ca8b720110482a66c8dda2e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Sep 2026 16:00:10 +0200 Subject: [PATCH 21/28] Rustup to rustc 1.100.0-nightly (f248f4038 2026-09-05) --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e203b3305eda1..e86e753e49c5a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-08-24" +channel = "nightly-2026-09-06" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From ba9ce941eab342e2e25c227177d8029b030b6660 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Sep 2026 18:51:58 +0200 Subject: [PATCH 22/28] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 4db6fe35f65c6..5a1374fe56e09 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -138,6 +138,7 @@ rm -r tests/run-make/panic-impl-transitive rm tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs rm tests/ui/statics/issue-91050-1.rs rm tests/ui/statics/issue-91050-2.rs +rm -r tests/run-make/locate-panic-runtime # giving different but possibly correct results # ============================================= @@ -157,6 +158,7 @@ rm -r tests/run-make/strip # same rm -r tests/run-make-cargo/compiler-builtins # Expects lib/rustlib/src/rust to contains the standard library source rm -r tests/run-make-cargo/panic-immediate-abort-works # same rm -r tests/run-make-cargo/panic-immediate-abort-codegen # same +rm -r tests/run-make-cargo/panic-strategies # same rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features rm -r tests/run-make/const-trait-stable-toolchain # same rm -r tests/run-make/print-request-help-stable-unstable # same From 50311ddcd1a2a7a8ef93af5d8eef3bb082a9b526 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:47:15 +0200 Subject: [PATCH 23/28] Remove stabilized feature gate --- example/mini_core_hello_world.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 5e986201b385c..9a710caae9cd1 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,7 +1,6 @@ #![feature( no_core, lang_items, - never_type, extern_types, thread_local, repr_simd, From ac12e6fd52d6c4d75b468f3193aa45323a4fa4ee Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Mon, 7 Sep 2026 14:46:05 -0400 Subject: [PATCH 24/28] Improve keep-in-sync comments --- compiler/rustc_data_structures/src/profiling.rs | 6 +++--- compiler/rustc_session/src/options.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 41e5f7ae67ab0..f746e1756fe94 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -120,7 +120,7 @@ bitflags::bitflags! { /// Store aggregated counts of cache hits per query invocation. const QUERY_CACHE_HIT_COUNTS = 1 << 10; - // keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs + // keep this in sync with the `-Z self-profile-events` help message in rustc_session/src/options.rs const DEFAULT = Self::GENERIC_ACTIVITIES.bits() | Self::QUERY_PROVIDERS.bits() | Self::QUERY_BLOCKED.bits() | @@ -129,13 +129,13 @@ bitflags::bitflags! { Self::ARTIFACT_SIZES.bits() | Self::QUERY_CACHE_HIT_COUNTS.bits(); - // keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs + // keep this in sync with the `-Z self-profile-events` help message in rustc_session/src/options.rs const ARGS = Self::QUERY_KEYS.bits() | Self::FUNCTION_ARGS.bits(); const QUERY_CACHE_HIT_COMBINED = Self::QUERY_CACHE_HITS.bits() | Self::QUERY_CACHE_HIT_COUNTS.bits(); } } -// keep this in sync with the `-Z self-profile-events` help message in rustc_session/options.rs +// keep this in sync with the `-Z self-profile-events` help message in rustc_session/src/options.rs const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("none", EventFilter::empty()), ("all", EventFilter::all()), diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 753eebdb3f39f..b6ef067a5ec25 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2839,7 +2839,7 @@ written to standard error output)"), `instructions:u` (retired instructions, userspace-only) `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)" ), - /// keep this in sync with the event filter names in librustc_data_structures/profiling.rs + /// keep this in sync with the event filter names and defaults in rustc_data_structures/src/profiling.rs self_profile_events: Option> = (None, parse_opt_comma_list, [UNTRACKED], "specify the events recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` From d571cae83e0129ae7669f77a9835dc2695aae461 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Sep 2026 08:27:49 +1000 Subject: [PATCH 25/28] Minimize `DiagCtxt` methods We have `DiagCtxt`, `DiagCtxtInner`, and `DiagCtxtHandle`. They're all necessary, but the method placement is inconsistent. This commit establishes a clearer rule: methods should *not* go on `DiagCtxt` whenever possible. Benefits: - Simpler rule for deciding where to put a method. - `impl Deref for DiagCtxtHandle` can be removed, including its non-standard double-reference `&&'a DiagCtxt` return value. This makes it impossible to accidentally discard a taint target by calling `handle` on a `DiagCtxtHandle`. - Catches some places where we were calling `dcx.handle()` when `dcx` was already a handle. --- compiler/rustc_borrowck/src/root_cx.rs | 2 +- compiler/rustc_codegen_ssa/src/back/lto.rs | 8 +- compiler/rustc_driver_impl/src/lib.rs | 10 +- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_errors/src/lib.rs | 103 ++++++++++----------- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 2 +- src/tools/clippy/src/driver.rs | 2 +- 8 files changed, 63 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs index b1aca758d64ae..1cd39f5089617 100644 --- a/compiler/rustc_borrowck/src/root_cx.rs +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -76,7 +76,7 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> { } pub(super) fn dcx(&self) -> DiagCtxtHandle<'diag> { - self.tcx.dcx().taintable_handle(&self.tainted_by_errors) + self.tcx.dcx().into_taintable(&self.tainted_by_errors) } pub(super) fn used_mut_upvars( diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index 31fae5b4f96b0..a1de6b709cd92 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -145,17 +145,17 @@ pub(super) fn check_lto_allowed(cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>) // Make sure we actually can run LTO for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { - dcx.handle().emit_fatal(LtoDisallowed); + dcx.emit_fatal(LtoDisallowed); } else if *crate_type == CrateType::Dylib { if !cgcx.dylib_lto { - dcx.handle().emit_fatal(LtoDylib); + dcx.emit_fatal(LtoDylib); } } else if *crate_type == CrateType::ProcMacro && !cgcx.dylib_lto { - dcx.handle().emit_fatal(LtoProcMacro); + dcx.emit_fatal(LtoProcMacro); } } if cgcx.prefer_dynamic && !cgcx.dylib_lto { - dcx.handle().emit_fatal(DynamicLinkingWithLTO); + dcx.emit_fatal(DynamicLinkingWithLTO); } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e4a307a2224d8..c935efe71edc1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -35,7 +35,7 @@ use rustc_data_structures::profiling::{ }; pub use rustc_errors::catch_fatal_errors; use rustc_errors::emitter::stderr_destination; -use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown}; +use rustc_errors::{ColorConfig, DiagCtxt, DiagCtxtHandle, ErrCode, PResult, markdown}; use rustc_feature::find_gated_cfg; // This avoids a false positive with `-Wunused_crate_dependencies`. // `rust_index` isn't used in this crate's code, but it must be named in the @@ -1442,7 +1442,7 @@ pub static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false); /// extra_info. /// /// A custom rustc driver can skip calling this to set up a custom ICE hook. -pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt)) { +pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(DiagCtxtHandle<'_>)) { // If the user has not explicitly overridden "RUST_BACKTRACE", then produce // full backtraces. When a compiler ICE happens, we want to gather // as much information as possible to present in the issue opened @@ -1524,14 +1524,14 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt)) fn report_ice( info: &panic::PanicHookInfo<'_>, bug_report_url: &str, - extra_info: fn(&DiagCtxt), + extra_info: fn(DiagCtxtHandle<'_>), using_internal_features: &AtomicBool, ) { let emitter = Box::new(rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter::new( stderr_destination(rustc_errors::ColorConfig::Auto), )); - let dcx = rustc_errors::DiagCtxt::new(emitter); + let dcx = DiagCtxt::new(emitter); let dcx = dcx.handle(); // a .span_bug or .bug call has already printed what @@ -1602,7 +1602,7 @@ fn report_ice( // We don't trust this callback not to panic itself, so run it at the end after we're sure we've // printed all the relevant info. - extra_info(&dcx); + extra_info(dcx); #[cfg(windows)] if env::var("RUSTC_BREAK_ON_ICE").is_ok() { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index d1dc3ab6e9525..2874b85e9b67a 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1345,7 +1345,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { s } - /// See `DiagCtxt::stash_diagnostic` for details. + /// See `DiagCtxtHandle::stash_diagnostic` for details. pub fn stash(mut self, span: Span, key: StashKey) -> Option { let diag = self.take_diag(); self.dcx.stash_diagnostic(span, key, diag) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f868b11ea6fd2..98a5b32e5d902 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -269,6 +269,9 @@ pub struct DelayedBugPanic; /// A `DiagCtxt` deals with errors and other compiler output. /// Certain errors (fatal, bug, unimpl) may cause immediate exit, /// others log errors for later reporting. +/// +/// Note: methods should be implemented not on this type but on `DiagCtxtHandle` or +/// `DiagCtxtInner`, whenever possible. pub struct DiagCtxt { inner: Lock, } @@ -281,17 +284,12 @@ pub struct DiagCtxtHandle<'a> { tainted_with_errors: Option<&'a Cell>>, } -impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { - type Target = &'a DiagCtxt; - - fn deref(&self) -> &Self::Target { - &self.dcx - } -} - /// This inner struct exists to keep it all behind a single lock; /// this is done to prevent possible deadlocks in a multi-threaded compiler, /// as well as inconsistent state observation. +/// +/// Note: methods should be implemented not on this type but on `DiagCtxtHandle` whenever possible. +/// Methods on this type should only be used e.g. when the lock is already held. struct DiagCtxtInner { flags: DiagCtxtFlags, @@ -497,20 +495,25 @@ impl DiagCtxt { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } + pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> { + DiagCtxtHandle { dcx: self, tainted_with_errors: None } + } +} + +impl<'a> DiagCtxtHandle<'a> { pub fn make_silent(&self) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); inner.emitter = Box::new(emitter::SilentEmitter {}); } pub fn set_emitter(&self, emitter: Box) { - self.inner.borrow_mut().emitter = emitter; + self.dcx.inner.borrow_mut().emitter = emitter; } - // This is here to not allow mutation of flags; - // as of this writing it's used in Session::consider_optimizing and - // in tests in rustc_interface. + // This is here to not allow mutation of flags; as of this writing it's used in + // `emit_lint_base` and in tests in `rustc_interface`. pub fn can_emit_warnings(&self) -> bool { - self.inner.borrow_mut().flags.can_emit_warnings + self.dcx.inner.borrow().flags.can_emit_warnings } /// Resets the diagnostic error count as well as the cached emitted diagnostics. @@ -521,7 +524,7 @@ impl DiagCtxt { pub fn reset_err_count(&self) { // Use destructuring so that if a field gets added to `DiagCtxtInner`, it's impossible to // fail to update this method as well. - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); let DiagCtxtInner { flags: _, err_guars, @@ -563,22 +566,16 @@ impl DiagCtxt { *fulfilled_expectations = Default::default(); } - pub fn handle<'a>(&'a self) -> DiagCtxtHandle<'a> { - DiagCtxtHandle { dcx: self, tainted_with_errors: None } - } - /// Link this to a taintable context so that emitting errors will automatically set /// the `Option` instead of having to do that manually at every error /// emission site. - pub fn taintable_handle<'a>( - &'a self, + pub fn into_taintable( + self, tainted_with_errors: &'a Cell>, ) -> DiagCtxtHandle<'a> { - DiagCtxtHandle { dcx: self, tainted_with_errors: Some(tainted_with_errors) } + DiagCtxtHandle { dcx: self.dcx, tainted_with_errors: Some(tainted_with_errors) } } -} -impl<'a> DiagCtxtHandle<'a> { /// Stashes a diagnostic for possible later improvement in a different, /// later stage of the compiler. Possible actions depend on the diagnostic /// level: @@ -618,7 +615,7 @@ impl<'a> DiagCtxtHandle<'a> { // diagnostic context is dropped and thus delayed bugs are emitted. Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))), DelayedBug => { - return self.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); + return self.dcx.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); } ForceWarning | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow | Expect => None, @@ -627,7 +624,8 @@ impl<'a> DiagCtxtHandle<'a> { // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. // See the PR for a discussion. - self.inner + self.dcx + .inner .borrow_mut() .stashed_diagnostics .entry(key) @@ -642,9 +640,10 @@ impl<'a> DiagCtxtHandle<'a> { /// error. pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { // FIXME(#120456) - is `swap_remove` correct? - let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( - |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), - )?; + let (diag, guar, _) = + self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), + )?; assert!(!diag.is_error()); assert!(guar.is_none()); Some(Diag::new_diagnostic(self, diag)) @@ -664,7 +663,7 @@ impl<'a> DiagCtxtHandle<'a> { F: FnMut(&mut Diag<'_>), { // FIXME(#120456) - is `swap_remove` correct? - let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + let err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); err.map(|(err, guar, _)| { @@ -688,7 +687,7 @@ impl<'a> DiagCtxtHandle<'a> { new_err: Diag<'_>, ) -> ErrorGuaranteed { // FIXME(#120456) - is `swap_remove` correct? - let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + let old_err = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); match old_err { @@ -705,7 +704,7 @@ impl<'a> DiagCtxtHandle<'a> { } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { - let inner = self.inner.borrow(); + let inner = self.dcx.inner.borrow(); if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key) && !stashed_diagnostics.is_empty() { @@ -717,13 +716,13 @@ impl<'a> DiagCtxtHandle<'a> { /// Emit all stashed diagnostics. pub fn emit_stashed_diagnostics(&self) -> Option { - self.inner.borrow_mut().emit_stashed_diagnostics() + self.dcx.inner.borrow_mut().emit_stashed_diagnostics() } /// This excludes delayed bugs. #[inline] pub fn err_count(&self) -> usize { - let inner = self.inner.borrow(); + let inner = self.dcx.inner.borrow(); inner.err_guars.len() + inner.lint_err_guars.len() + inner @@ -738,7 +737,7 @@ impl<'a> DiagCtxtHandle<'a> { /// Like [`DiagCtxtHandle::err_count`], but only counts errors whose recorded /// emitting thread is the calling thread. pub fn err_count_on_current_thread(&self) -> usize { - let inner = self.inner.borrow(); + let inner = self.dcx.inner.borrow(); let current = std::thread::current().id(); inner.err_guars.iter().filter(|(_, thread)| *thread == current).count() + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count() @@ -756,22 +755,22 @@ impl<'a> DiagCtxtHandle<'a> { /// This excludes lint errors and delayed bugs. Unless absolutely /// necessary, prefer `has_errors` to this method. pub fn has_errors_excluding_lint_errors(&self) -> Option { - self.inner.borrow().has_errors_excluding_lint_errors() + self.dcx.inner.borrow().has_errors_excluding_lint_errors() } /// This excludes delayed bugs. pub fn has_errors(&self) -> Option { - self.inner.borrow().has_errors() + self.dcx.inner.borrow().has_errors() } /// This excludes nothing. Unless absolutely necessary, prefer `has_errors` /// to this method. pub fn has_errors_or_delayed_bugs(&self) -> Option { - self.inner.borrow().has_errors_or_delayed_bugs() + self.dcx.inner.borrow().has_errors_or_delayed_bugs() } pub fn print_error_count(&self) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); // Any stashed diagnostics should have been handled by // `emit_stashed_diagnostics` by now. @@ -869,27 +868,27 @@ impl<'a> DiagCtxtHandle<'a> { /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. pub fn must_teach(&self, code: ErrCode) -> bool { - self.inner.borrow_mut().taught_diagnostics.insert(code) + self.dcx.inner.borrow_mut().taught_diagnostics.insert(code) } pub fn emit_diagnostic(&self, diagnostic: DiagInner) -> Option { - self.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) + self.dcx.inner.borrow_mut().emit_diagnostic(diagnostic, self.tainted_with_errors) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { - self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); + self.dcx.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); } pub fn emit_timing_section_start(&self, record: TimingRecord) { - self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start); + self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start); } pub fn emit_timing_section_end(&self, record: TimingRecord) { - self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End); + self.dcx.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End); } pub fn emit_future_breakage_report(&self) { - let inner = &mut *self.inner.borrow_mut(); + let inner = &mut *self.dcx.inner.borrow_mut(); let diags = mem::take(&mut inner.future_breakage_diagnostics); if !diags.is_empty() { inner.emitter.emit_future_breakage_report(diags); @@ -902,7 +901,7 @@ impl<'a> DiagCtxtHandle<'a> { loud: bool, unused_externs: &[&str], ) { - let mut inner = self.inner.borrow_mut(); + let mut inner = self.dcx.inner.borrow_mut(); // This "error" is an odd duck. // - It's only produce with JSON output. @@ -930,7 +929,7 @@ impl<'a> DiagCtxtHandle<'a> { /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. #[must_use] pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet { - mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) + mem::take(&mut self.dcx.inner.borrow_mut().fulfilled_expectations) } /// Trigger an ICE if there are any delayed bugs and no hard errors. @@ -938,7 +937,7 @@ impl<'a> DiagCtxtHandle<'a> { /// This will panic if there are any stashed diagnostics. You can call /// `emit_stashed_diagnostics` to emit those before calling `flush_delayed`. pub fn flush_delayed(&self) { - self.inner.borrow_mut().flush_delayed(); + self.dcx.inner.borrow_mut().flush_delayed(); } /// Used when trimmed_def_paths is called and we must produce a diagnostic @@ -946,10 +945,10 @@ impl<'a> DiagCtxtHandle<'a> { #[track_caller] pub fn set_must_produce_diag(&self) { assert!( - self.inner.borrow().must_produce_diag.is_none(), + self.dcx.inner.borrow().must_produce_diag.is_none(), "should only need to collect a backtrace once" ); - self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture()); + self.dcx.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture()); } } @@ -1186,10 +1185,6 @@ impl<'a> DiagCtxtHandle<'a> { } } -// Note: we prefer implementing operations on `DiagCtxt`, rather than -// `DiagCtxtInner`, whenever possible. This minimizes functions where -// `DiagCtxt::foo()` just borrows `inner` and forwards a call to -// `DiagCtxtInner::foo`. impl DiagCtxtInner { fn new(emitter: Box) -> Self { Self { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2e4da8d948f07..618de2c5356d6 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -491,7 +491,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn dcx(&self) -> DiagCtxtHandle<'_> { - self.tcx.dcx().taintable_handle(&self.tainted_by_errors) + self.tcx.dcx().into_taintable(&self.tainted_by_errors) } fn item_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 56fcc72bd9769..ad469ac8f86d3 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -723,7 +723,7 @@ impl<'tcx> InferOk<'tcx, ()> { impl<'tcx> InferCtxt<'tcx> { pub fn dcx(&self) -> DiagCtxtHandle<'_> { - self.tcx.dcx().taintable_handle(&self.tainted_by_errors) + self.tcx.dcx().into_taintable(&self.tainted_by_errors) } pub fn next_trait_solver(&self) -> bool { diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 78b9b2cd8de39..16c3a6434f35a 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -203,7 +203,7 @@ fn main() -> ExitCode { // as simple as moving the call from the hook to main, because `install_ice_hook` doesn't // accept a generic closure. let version_info = rustc_tools_util::get_version_info!(); - dcx.handle().note(format!("Clippy version: {version_info}")); + dcx.note(format!("Clippy version: {version_info}")); }); rustc_driver::catch_with_exit_code(move || { From db693f7dbcfab9af2a89b703096f692417e2f756 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 8 Sep 2026 12:08:21 +0200 Subject: [PATCH 26/28] Rustup to rustc 1.100.0-nightly (cea272fa3 2026-09-07) --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e86e753e49c5a..bc8bfacba1923 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-06" +channel = "nightly-2026-09-08" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 159e9615f8afcef9ebd539c87370b9ff7bd6a4a0 Mon Sep 17 00:00:00 2001 From: apiraino Date: Wed, 9 Sep 2026 11:58:32 +0200 Subject: [PATCH 27/28] Add a mention to docs about promoting and demoting platform support --- src/doc/rustc/src/platform-support.md | 6 ++++++ src/doc/rustc/src/target-tier-policy.md | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 54d9885c93955..b6bf18a155051 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -15,6 +15,12 @@ the compiler what kind of output should be produced. Component availability is tracked [here](https://rust-lang.github.io/rustup-components-history/). +Support for targets can vary during their lifespan (a target con be promoted because the support +improves or can be demoted because lack of resources). Procedures for promoting and demoting targets +are documented at our [Forge documentation site][forge]. + +[forge]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#targets + ## Tier 1 with Host Tools Tier 1 targets can be thought of as "guaranteed to work". The Rust project diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index ed725258fa7fb..e3da487da739b 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -4,6 +4,7 @@ * [General](#general) * [Adding a new target](#adding-a-new-target) +* [Promoting or demoting a target](#promoting-or-demoting-a-target) * [Tier 3 target policy](#tier-3-target-policy) * [Tier 2 target policy](#tier-2-target-policy) * [Tier 2 with host tools](#tier-2-with-host-tools) @@ -140,6 +141,14 @@ support for the target in `cc` and `libc`. [`rust-lang/rust`]: https://github.com/rust-lang/rust [rustc_dev_guide_add_target]: https://rustc-dev-guide.rust-lang.org/building/new-target.html +## Promoting or demoting a target + +Support for targets can vary during their lifespan (a target con be promoted because the support +improves or can be demoted because lack of resources). Procedures for promoting and demoting targets +are documented at our [Forge documentation site][forge]. + +[forge]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#targets + ## Tier 3 target policy At this tier, the Rust project provides no official support for a target, so we From d64cce9c3b3c374cfaaa9b6dac270a6bbf152812 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:47:02 +0200 Subject: [PATCH 28/28] Pass -Zforce-unstable-if-unmarked to cg_clif tests This makes their test environment consistent between runs inside the cg_clif and rust repos. --- compiler/rustc_codegen_cranelift/build_system/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index c7b61f519d247..5ae76dc1e591e 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -478,6 +478,8 @@ impl<'a> TestRunner<'a> { cmd.arg("--check-cfg=cfg(jit)"); cmd.arg("--check-cfg=cfg(target_has_reliable_f128)"); cmd.arg("--edition=2024"); + // implicitly passed when building inside the rust repo + cmd.arg("-Zforce-unstable-if-unmarked"); cmd.args(args); cmd }