From a4c0bf5edaec5bc09ef47f3b4bef6ace2a7c551a Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 2 Feb 2026 12:04:56 +0000 Subject: [PATCH 01/45] switch to v0 mangling by default on stable Following rust-lang/rust#89117, rustc has defaulted to the v0 mangling scheme by default (since Nov 20th 2025). This surfaced two bugs: - rust-lang/rust#138261 was a small ICE (found via fuzzing) where an implementation-internal namespace was missing for global assembly - this occurs with names instantiated within global assembly (that can happen inside constants) - rust-lang/rust#134479 only occurs with unstable `generic_const_exprs` Since there have been three-to-four months for users to find bugs with this mangling scheme on nightly, that the scheme has been waiting many years to be stabilised, and has been used successfully internally at Microsoft, Meta and Google for many years, this patch proposes stabilising the v0 mangling scheme on stable. This patch does not propose removing the legacy mangling, it will remain usable on nightly as an escape-hatch if there are remaining bugs (though admittedly it would require switching to nightly for those on stable) - it is anticipated that this would be unlikely given current testing undergone by v0. Legacy mangling can be removed in another follow-up. --- compiler/rustc_session/src/config.rs | 6 +----- compiler/rustc_session/src/options.rs | 2 +- src/bootstrap/src/core/builder/cargo.rs | 13 ++----------- src/doc/rustc/src/symbol-mangling/index.md | 7 +++---- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5e2671ef4ef6b..8ebb5233f6c80 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1483,11 +1483,7 @@ impl Options { } pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { - self.cg.symbol_mangling_version.unwrap_or(if self.unstable_features.is_nightly_build() { - SymbolManglingVersion::V0 - } else { - SymbolManglingVersion::Legacy - }) + self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::V0) } #[inline] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9219b5a7e8aca..cd0dc97c97a59 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2194,7 +2194,7 @@ options! { "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, parse_symbol_mangling_version, [TRACKED], - "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"), + "which mangling version to use for symbol names ('legacy', 'v0' (default), or 'hashed')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 7150b2b0d59f2..1d7285e7c7519 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -664,16 +664,6 @@ impl Builder<'_> { rustflags.arg(sysroot_str); } - let use_new_symbol_mangling = self.config.rust_new_symbol_mangling.or_else(|| { - if mode != Mode::Std { - // The compiler and tools default to the new scheme - Some(true) - } else { - // std follows the flag's default, which per compiler-team#938 is v0 on nightly - None - } - }); - // By default, windows-rs depends on a native library that doesn't get copied into the // sysroot. Passing this cfg enables raw-dylib support instead, which makes the native // library unnecessary. This can be removed when windows-rs enables raw-dylib @@ -683,7 +673,8 @@ impl Builder<'_> { rustflags.arg("--cfg=windows_raw_dylib"); } - if let Some(usm) = use_new_symbol_mangling { + // When unset, follow the default of the compiler flag - the compiler, tools and std use v0 + if let Some(usm) = self.config.rust_new_symbol_mangling { rustflags.arg(if usm { "-Csymbol-mangling-version=v0" } else { diff --git a/src/doc/rustc/src/symbol-mangling/index.md b/src/doc/rustc/src/symbol-mangling/index.md index ad565da9746cb..3f7d55063ca6a 100644 --- a/src/doc/rustc/src/symbol-mangling/index.md +++ b/src/doc/rustc/src/symbol-mangling/index.md @@ -46,7 +46,6 @@ foo::example_function ## Mangling versions -`rustc` supports different mangling versions which encode the names in different ways. -The legacy version (which is currently the default on beta/stable) is not described here. -The "v0" mangling scheme addresses several limitations of the legacy format, -and is described in the [v0 Symbol Format](v0.md) chapter. +There is currently one stable mangling scheme version - `v0`. On nightly builds, rustc supports +switching back to the `legacy` mangling scheme using [`-C symbol-mangling-version`]. The `v0` +mangling scheme is described in the [v0 Symbol Format](v0.md) chapter. From c3ef307d1bc769136e8ce73453f8857f979a60e2 Mon Sep 17 00:00:00 2001 From: N1ark Date: Sun, 15 Mar 2026 22:41:07 +0000 Subject: [PATCH 02/45] Merge `fabsfN` into `fabs::` Add `bounds::FloatPrimitive` Exhaustive float pattern match Fix GCC use span bugs --- src/intrinsics/mod.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 8b112e695275a..780550fc4cc74 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -346,10 +346,6 @@ fn codegen_float_intrinsic_call<'tcx>( 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::fabsf16 => ("fabsf16", 1, fx.tcx.types.f16, types::F16), - sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32), - sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), - sym::fabsf128 => ("fabsf128", 1, fx.tcx.types.f128, types::F128), sym::fmaf16 => ("fmaf16", 3, fx.tcx.types.f16, types::F16), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), @@ -441,11 +437,7 @@ fn codegen_float_intrinsic_call<'tcx>( sym::copysignf32 | sym::copysignf64 => { CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) } - sym::fabsf16 => CValue::by_val(codegen_f16_f128::abs_f16(fx, args[0]), layout), - sym::fabsf128 => CValue::by_val(codegen_f16_f128::abs_f128(fx, args[0]), layout), - sym::fabsf32 - | sym::fabsf64 - | sym::floorf32 + sym::floorf32 | sym::floorf64 | sym::ceilf32 | sym::ceilf64 @@ -456,7 +448,6 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::sqrtf32 | sym::sqrtf64 => { let val = match intrinsic { - sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]), 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]), @@ -1179,6 +1170,28 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } + sym::fabs => { + intrinsic_args!(fx, args => (arg); intrinsic); + let layout = arg.layout(); + let ty::Float(float_ty) = layout.ty.kind() else { + span_bug!( + source_info.span, + "expected float type for fabs intrinsic: {:?}", + layout.ty + ); + }; + let x = arg.load_scalar(fx); + let val = match float_ty { + FloatTy::F32 | FloatTy::F64 => 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), + }; + let val = CValue::by_val(val, layout); + ret.write_cvalue(fx, val); + } + sym::minimumf16 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); From a3741b2aef6f557b9fb52a07e5d4ebda0ad8bd56 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 18 Mar 2026 15:04:47 +0100 Subject: [PATCH 03/45] simd_fmin/fmax: make semantics and name consistent with scalar intrinsics --- example/float-minmax-pass.rs | 16 ++++++++-------- src/intrinsics/simd.rs | 10 +++++++--- src/num.rs | 4 ++-- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/example/float-minmax-pass.rs b/example/float-minmax-pass.rs index b7491b7e522f3..206c56e887c7d 100644 --- a/example/float-minmax-pass.rs +++ b/example/float-minmax-pass.rs @@ -33,24 +33,24 @@ fn main() { let n = f32x4([nan, nan, nan, nan]); unsafe { - let min0 = simd_fmin(x, y); - let min1 = simd_fmin(y, x); + let min0 = simd_minimum_number_nsz(x, y); + let min1 = simd_minimum_number_nsz(y, x); assert_eq!(min0.into_array(), min1.into_array()); let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0.into_array(), e.into_array()); - let minn = simd_fmin(x, n); + let minn = simd_minimum_number_nsz(x, n); assert_eq!(minn.into_array(), x.into_array()); - let minn = simd_fmin(y, n); + let minn = simd_minimum_number_nsz(y, n); assert_eq!(minn.into_array(), y.into_array()); - let max0 = simd_fmax(x, y); - let max1 = simd_fmax(y, x); + let max0 = simd_maximum_number_nsz(x, y); + let max1 = simd_maximum_number_nsz(y, x); assert_eq!(max0.into_array(), max1.into_array()); let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0.into_array(), e.into_array()); - let maxn = simd_fmax(x, n); + let maxn = simd_maximum_number_nsz(x, n); assert_eq!(maxn.into_array(), x.into_array()); - let maxn = simd_fmax(y, n); + let maxn = simd_maximum_number_nsz(y, n); assert_eq!(maxn.into_array(), y.into_array()); } } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 200cedf0f6ae0..cc2311a67b5d5 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -493,7 +493,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } } - sym::simd_fmin | sym::simd_fmax => { + sym::simd_minimum_number_nsz | sym::simd_maximum_number_nsz => { intrinsic_args!(fx, args => (x, y); intrinsic); if !x.layout().ty.is_simd() { @@ -508,8 +508,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!("{:?}", lane_ty), } match intrinsic { - sym::simd_fmin => crate::num::codegen_float_min(fx, x_lane, y_lane), - sym::simd_fmax => crate::num::codegen_float_max(fx, x_lane, y_lane), + sym::simd_minimum_number_nsz => { + crate::num::codegen_float_min(fx, x_lane, y_lane) + } + sym::simd_maximum_number_nsz => { + crate::num::codegen_float_max(fx, x_lane, y_lane) + } _ => unreachable!(), } }); diff --git a/src/num.rs b/src/num.rs index 0459644e16aa7..e583f3f2f754a 100644 --- a/src/num.rs +++ b/src/num.rs @@ -500,8 +500,8 @@ fn codegen_ptr_binop<'tcx>( // In Rust floating point min and max don't propagate NaN (not even SNaN). In Cranelift they do // however. For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for -// `minnumf*` and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by -// comparing a float against itself. Only in case of NaN is it not equal to itself. +// `minimum_number_nsz` and `a.is_nan() ? b : (a <= b ? b : a)` for `maximum_number_nsz`. NaN checks +// are done by comparing a float against itself. Only in case of NaN is it not equal to itself. pub(crate) fn codegen_float_min(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value { // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift `fcmp` once // `f16`/`f128` backend lowerings have been added to Cranelift. From 9a925322aca86a828c5515c4f92b94e436210e29 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:43:04 +0100 Subject: [PATCH 04/45] Merge commit '493d427c7d3423f085f05179e36a35b4943b1379' into sync_cg_clif-2026-03-25 --- .github/workflows/abi-cafe.yml | 4 +- .github/workflows/audit.yml | 18 --- .github/workflows/main.yml | 32 ++-- .github/workflows/rustc.yml | 8 +- Cargo.lock | 142 ++++++++++-------- Cargo.toml | 28 ++-- build_system/main.rs | 9 +- build_system/todo.rs | 70 +++++++++ build_system/usage.txt | 1 + clean_all.sh | 6 - example/mini_core.rs | 4 +- example/mini_core_hello_world.rs | 12 +- example/neon.rs | 2 +- example/std_example.rs | 100 ++++++++++-- ...0027-stdlib-128bit-atomic-operations.patch | 13 +- rust-toolchain.toml | 2 +- scripts/setup_rust_fork.sh | 18 +-- scripts/test_rustc_tests.sh | 2 - src/global_asm.rs | 16 +- src/inline_asm.rs | 112 ++++++++------ 20 files changed, 386 insertions(+), 213 deletions(-) delete mode 100644 .github/workflows/audit.yml create mode 100644 build_system/todo.rs diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index 3367562f26838..c11fc5921ef11 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -43,7 +43,7 @@ jobs: # TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: CPU features if: matrix.os == 'ubuntu-latest' @@ -56,7 +56,7 @@ jobs: run: .github/scripts/free-disk-space.sh - name: Cache cargo target dir - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml deleted file mode 100644 index 95a4dcd3266df..0000000000000 --- a/.github/workflows/audit.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Security audit -on: - workflow_dispatch: - schedule: - - cron: '0 10 * * 1' # every monday at 10:00 UTC -permissions: - issues: write - checks: write -jobs: - audit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: | - sed -i 's/components.*/components = []/' rust-toolchain.toml - - uses: rustsec/audit-check@v2.0.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 07d9af4a9b54a..7f9fd0cc7c5e0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,12 +19,22 @@ env: RUSTFLAGS: "-Dwarnings" jobs: + todo_check: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v6 + + - name: Check todo + run: ./y.sh check-todo + rustfmt: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Avoid installing rustc-dev run: | @@ -78,14 +88,14 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: CPU features if: matrix.os == 'ubuntu-latest' run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }} @@ -127,7 +137,7 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: CPU features run: cat /proc/cpuinfo @@ -149,13 +159,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: build/cg_clif key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }} @@ -201,10 +211,10 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Cache cargo target dir - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }} @@ -223,7 +233,7 @@ jobs: run: tar cvfJ cg_clif.tar.xz dist - name: Upload prebuilt cg_clif - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cg_clif-${{ matrix.env.TARGET_TRIPLE }} path: cg_clif.tar.xz @@ -232,7 +242,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 if: ${{ github.ref == 'refs/heads/main' }} - needs: [rustfmt, test, bench, dist] + needs: [todo_check, rustfmt, test, bench, dist] permissions: contents: write # for creating the dev tag and release @@ -242,7 +252,7 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Download all built artifacts uses: actions/download-artifact@v4 diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index b22725fdc9d41..0f91bc11753eb 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -11,13 +11,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: build/cg_clif key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain.toml', 'Cargo.lock') }} @@ -31,13 +31,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: build/cg_clif key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain.toml', 'Cargo.lock') }} diff --git a/Cargo.lock b/Cargo.lock index afc1d0d0ab959..2d84d2c57fc6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" dependencies = [ "allocator-api2", ] @@ -43,42 +43,46 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cranelift-assembler-x64" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0377b13bf002a0774fcccac4f1102a10f04893d24060cf4b7350c87e4cbb647c" +checksum = "4f248321c6a7d4de5dcf2939368e96a397ad3f53b6a076e38d0104d1da326d37" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa027979140d023b25bf7509fb7ede3a54c3d3871fb5ead4673c4b633f671a2" +checksum = "ab6d78ff1f7d9bf8b7e1afbedbf78ba49e38e9da479d4c8a2db094e22f64e2bc" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618e4da87d9179a70b3c2f664451ca8898987aa6eb9f487d16988588b5d8cc40" +checksum = "6b6005ba640213a5b95382aeaf6b82bf028309581c8d7349778d66f27dc1180b" dependencies = [ "cranelift-entity", + "wasmtime-internal-core", ] [[package]] name = "cranelift-bitset" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db53764b5dad233b37b8f5dc54d3caa9900c54579195e00f17ea21f03f71aaa7" +checksum = "81fb5b134a12b559ff0c0f5af0fcd755ad380723b5016c4e0d36f74d39485340" +dependencies = [ + "wasmtime-internal-core", +] [[package]] name = "cranelift-codegen" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae927f1d8c0abddaa863acd201471d56e7fc6c3925104f4861ed4dc3e28b421" +checksum = "85837de8be7f17a4034a6b08816f05a3144345d2091937b39d415990daca28f4" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -90,21 +94,22 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown", + "hashbrown 0.16.1", + "libm", "log", "regalloc2", "rustc-hash", "serde", "smallvec", "target-lexicon", - "wasmtime-internal-math", + "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen-meta" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fcf1e3e6757834bd2584f4cbff023fcc198e9279dcb5d684b4bb27a9b19f54" +checksum = "e433faa87d38e5b8ff469e44a26fea4f93e58abd7a7c10bad9810056139700c9" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -114,33 +119,34 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205dcb9e6ccf9d368b7466be675ff6ee54a63e36da6fe20e72d45169cf6fd254" +checksum = "5397ba61976e13944ca71230775db13ee1cb62849701ed35b753f4761ed0a9b7" [[package]] name = "cranelift-control" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "108eca9fcfe86026054f931eceaf57b722c1b97464bf8265323a9b5877238817" +checksum = "cc81c88765580720eb30f4fc2c1bfdb75fcbf3094f87b3cd69cecca79d77a245" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d96496910065d3165f84ff8e1e393916f4c086f88ac8e1b407678bc78735aa" +checksum = "463feed5d46cf8763f3ba3045284cf706dd161496e20ec9c14afbb4ba09b9e66" dependencies = [ "cranelift-bitset", + "wasmtime-internal-core", ] [[package]] name = "cranelift-frontend" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e303983ad7e23c850f24d9c41fc3cb346e1b930f066d3966545e4c98dac5c9fb" +checksum = "a4c5eca7696c1c04ab4c7ed8d18eadbb47d6cc9f14ec86fe0881bf1d7e97e261" dependencies = [ "cranelift-codegen", "log", @@ -150,15 +156,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b0cf8d867d891245836cac7abafb0a5b0ea040a019d720702b3b8bcba40bfa" +checksum = "f1153844610cc9c6da8cf10ce205e45da1a585b7688ed558aa808bbe2e4e6d77" [[package]] name = "cranelift-jit" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf1e35da6eca2448395f483eb172ce71dd7842f7dc96f44bb8923beafe43c6d" +checksum = "41836de8321b303d3d4188e58cc09c30c7645337342acfcfb363732695cae098" dependencies = [ "anyhow", "cranelift-codegen", @@ -176,9 +182,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "792ba2a54100e34f8a36e3e329a5207cafd1f0918a031d34695db73c163fdcc7" +checksum = "b731f66cb1b69b60a74216e632968ebdbb95c488d26aa1448ec226ae0ffec33e" dependencies = [ "anyhow", "cranelift-codegen", @@ -187,9 +193,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24b641e315443e27807b69c440fe766737d7e718c68beb665a2d69259c77bf3" +checksum = "a97b583fe9a60f06b0464cee6be5a17f623fd91b217aaac99b51b339d19911af" dependencies = [ "cranelift-codegen", "libc", @@ -198,9 +204,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecba1f219a201cf946150538e631defd620c5051b62c52ecb89a0004bab263d4" +checksum = "9809d2d419cd18f17377f4ce64a7ad22eeda0d042c08833d3796657f1ddebc82" dependencies = [ "anyhow", "cranelift-codegen", @@ -213,9 +219,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.128.3" +version = "0.130.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e378a54e7168a689486d67ee1f818b7e5356e54ae51a1d7a53f4f13f7f8b7a" +checksum = "8594dc6bb4860fa8292f1814c76459dbfb933e1978d8222de6380efce45c7cee" [[package]] name = "crc32fast" @@ -233,24 +239,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "fallible-iterator" -version = "0.3.0" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "gimli" -version = "0.32.3" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" dependencies = [ - "fallible-iterator", + "fnv", + "hashbrown 0.16.1", "indexmap", "stable_deref_trait", ] @@ -260,6 +267,12 @@ name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "foldhash", ] @@ -272,12 +285,12 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.10.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", ] [[package]] @@ -325,12 +338,12 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "object" -version = "0.37.3" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" dependencies = [ "crc32fast", - "hashbrown", + "hashbrown 0.16.1", "indexmap", "memchr", ] @@ -355,13 +368,13 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.13.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" +checksum = "952ddbfc6f9f64d006c3efd8c9851a6ba2f2b944ba94730db255d55006e0ffda" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown", + "hashbrown 0.15.5", "log", "rustc-hash", "smallvec", @@ -468,24 +481,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "wasmtime-internal-jit-icache-coherence" -version = "41.0.3" +name = "wasmtime-internal-core" +version = "43.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bada5ca1cc47df7d14100e2254e187c2486b426df813cea2dd2553a7469f7674" +checksum = "e671917bb6856ae360cb59d7aaf26f1cfd042c7b924319dd06fd380739fc0b2e" dependencies = [ - "anyhow", - "cfg-if", - "libc", - "windows-sys 0.61.2", + "hashbrown 0.16.1", + "libm", ] [[package]] -name = "wasmtime-internal-math" -version = "41.0.3" +name = "wasmtime-internal-jit-icache-coherence" +version = "43.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf6f615d528eda9adc6eefb062135f831b5215c348f4c3ec3e143690c730605b" +checksum = "9b3112806515fac8495883885eb8dbdde849988ae91fe6beb544c0d7c0f4c9aa" dependencies = [ - "libm", + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a7b4664282eda..6707557f06f75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,15 +8,15 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.128.3", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.128.3" } -cranelift-module = { version = "0.128.3" } -cranelift-native = { version = "0.128.3" } -cranelift-jit = { version = "0.128.3", optional = true } -cranelift-object = { version = "0.128.3" } +cranelift-codegen = { version = "0.130.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.130.0" } +cranelift-module = { version = "0.130.0" } +cranelift-native = { version = "0.130.0" } +cranelift-jit = { version = "0.130.0", optional = true } +cranelift-object = { version = "0.130.0" } target-lexicon = "0.13" -gimli = { version = "0.32", default-features = false, features = ["write"] } -object = { version = "0.37.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +gimli = { version = "0.33", default-features = false, features = ["write"] } +object = { version = "0.38.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.9.0", optional = true } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-41.0.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/build_system/main.rs b/build_system/main.rs index 6251687babc67..0720d72c6d7cb 100644 --- a/build_system/main.rs +++ b/build_system/main.rs @@ -17,6 +17,7 @@ mod prepare; mod rustc_info; mod shared_utils; mod tests; +mod todo; mod utils; fn usage() { @@ -38,6 +39,7 @@ enum Command { Test, AbiCafe, Bench, + CheckTodo, } #[derive(Copy, Clone, Debug)] @@ -66,6 +68,7 @@ fn main() { Some("test") => Command::Test, Some("abi-cafe") => Command::AbiCafe, Some("bench") => Command::Bench, + Some("check-todo") => Command::CheckTodo, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -139,6 +142,10 @@ fn main() { process::exit(0); } + if command == Command::CheckTodo { + todo::run(); + } + let rustup_toolchain_name = match (env::var("CARGO"), env::var("RUSTC"), env::var("RUSTDOC")) { (Ok(_), Ok(_), Ok(_)) => None, (_, Err(_), Err(_)) => Some(rustc_info::get_toolchain_name()), @@ -202,7 +209,7 @@ fn main() { )) }; match command { - Command::Prepare => { + Command::Prepare | Command::CheckTodo => { // Handled above } Command::Test => { diff --git a/build_system/todo.rs b/build_system/todo.rs new file mode 100644 index 0000000000000..66b31a10a065d --- /dev/null +++ b/build_system/todo.rs @@ -0,0 +1,70 @@ +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::{fs, process}; + +const EXTENSIONS: &[&str] = + &["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"]; + +fn has_supported_extension(path: &Path) -> bool { + path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e))) +} + +fn list_tracked_files() -> Result, String> { + let output = Command::new("git") + .args(["ls-files", "-z"]) + .output() + .map_err(|e| format!("Failed to run `git ls-files`: {e}"))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("`git ls-files` failed: {stderr}")); + } + + let mut files = Vec::new(); + for entry in output.stdout.split(|b| *b == 0) { + if entry.is_empty() { + continue; + } + let path = std::str::from_utf8(entry).unwrap(); + files.push(PathBuf::from(path)); + } + + Ok(files) +} + +pub(crate) fn run() -> ! { + let files = list_tracked_files().unwrap(); + let mut error_count = 0; + // Avoid embedding the task marker in source so greps only find real occurrences. + let todo_marker = "todo".to_ascii_uppercase(); + + for file in files { + if !has_supported_extension(&file) { + continue; + } + + let bytes = fs::read(&file).unwrap(); + let contents = std::str::from_utf8(&bytes).unwrap(); + + for (i, line) in contents.split('\n').enumerate() { + let trimmed = line.trim(); + if trimmed.contains(&todo_marker) { + eprintln!( + "{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME", + file.display(), + i + 1, + todo_marker + ); + error_count += 1; + } + } + } + + if error_count == 0 { + process::exit(0); + } + + eprintln!("found {} {}(s)", error_count, todo_marker); + process::exit(1); +} diff --git a/build_system/usage.txt b/build_system/usage.txt index 6c98087e52399..572fe78058101 100644 --- a/build_system/usage.txt +++ b/build_system/usage.txt @@ -6,6 +6,7 @@ USAGE: ./y.sh test [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen] [--skip-test TESTNAME] ./y.sh abi-cafe [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen] ./y.sh bench [--sysroot none|clif|llvm] [--out-dir DIR] [--download-dir DIR] [--no-unstable-features] [--frozen] + ./y.sh check-todo OPTIONS: --sysroot none|clif|llvm diff --git a/clean_all.sh b/clean_all.sh index 4dbd9dac94a89..32ed19300ac6a 100755 --- a/clean_all.sh +++ b/clean_all.sh @@ -2,9 +2,3 @@ set -e rm -rf target/ build_system/target download/ build/ dist/ - -# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh -# FIXME remove at some point in the future -rm y.bin y.bin.dSYM y.exe y.pdb 2>/dev/null || true -rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/ -rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} diff --git a/example/mini_core.rs b/example/mini_core.rs index 5293b458d8c4f..218050982e6d3 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -9,9 +9,9 @@ rustc_private, transparent_unions, auto_traits, - freeze_impls, - thread_local + freeze_impls )] +#![cfg_attr(not(all(windows, target_env = "gnu")), feature(thread_local))] #![no_core] #![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)] diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 10549cd2a41e2..6734d19fbb48b 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,13 +1,5 @@ -#![feature( - no_core, - lang_items, - never_type, - linkage, - extern_types, - thread_local, - repr_simd, - rustc_private -)] +#![feature(no_core, lang_items, never_type, extern_types, thread_local, repr_simd, rustc_private)] +#![cfg_attr(not(any(jit, target_vendor = "apple", windows)), feature(linkage))] #![no_core] #![allow(dead_code, non_camel_case_types, internal_features)] diff --git a/example/neon.rs b/example/neon.rs index fb3e10a41c025..98a2a7af38f6b 100644 --- a/example/neon.rs +++ b/example/neon.rs @@ -1,6 +1,6 @@ // Most of these tests are copied from https://github.com/japaric/stdsimd/blob/0f4413d01c4f0c3ffbc5a69e9a37fbc7235b31a9/coresimd/arm/neon.rs -#![feature(portable_simd)] +#![cfg_attr(target_arch = "aarch64", feature(portable_simd))] #[cfg(target_arch = "aarch64")] use std::arch::aarch64::*; diff --git a/example/std_example.rs b/example/std_example.rs index 33db75f0943a9..f0e38ae0610c9 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -1,14 +1,8 @@ -#![feature( - core_intrinsics, - coroutines, - stmt_expr_attributes, - coroutine_trait, - repr_simd, - tuple_trait, - unboxed_closures -)] +#![feature(core_intrinsics, coroutines, coroutine_trait, repr_simd, tuple_trait, unboxed_closures)] #![allow(internal_features)] +#[cfg(target_arch = "x86_64")] +use std::arch::asm; #[cfg(target_arch = "x86_64")] use std::arch::x86_64::*; use std::hint::black_box; @@ -173,6 +167,9 @@ fn main() { rust_call_abi(); + // #[cfg(target_arch = "x86_64")] + // inline_asm_call_custom_abi(); + const fn no_str() -> Option> { None } @@ -279,6 +276,17 @@ unsafe fn test_simd() { #[cfg(not(jit))] test_crc32(); + + #[cfg(not(jit))] + test_xmm_roundtrip(); + #[cfg(not(jit))] + if is_x86_feature_detected!("avx") { + test_ymm_roundtrip(); + } + #[cfg(not(jit))] + if is_x86_feature_detected!("avx512f") { + test_zmm_roundtrip(); + } } } @@ -576,6 +584,65 @@ unsafe fn test_mm_cvtps_ph() { assert_eq_m128i(r, e); } +#[cfg(target_arch = "x86_64")] +#[cfg(not(jit))] +unsafe fn test_xmm_roundtrip() { + unsafe { + let input = [1u8; 16]; + let mut output = [0u8; 16]; + + asm!( + "movups {xmm}, [{input}]", + "movups [{output}], {xmm}", + input = in(reg) input.as_ptr(), + output = in(reg) output.as_mut_ptr(), + xmm = out(xmm_reg) _, + ); + + assert_eq!(input, output); + } +} + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "avx")] +#[cfg(not(jit))] +unsafe fn test_ymm_roundtrip() { + unsafe { + let input = [1u8; 32]; + let mut output = [0u8; 32]; + + asm!( + "vmovups {ymm}, [{input}]", + "vmovups [{output}], {ymm}", + input = in(reg) input.as_ptr(), + output = in(reg) output.as_mut_ptr(), + ymm = out(ymm_reg) _, + ); + + assert_eq!(input, output); + } +} + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "avx512f")] +#[cfg(not(jit))] +unsafe fn test_zmm_roundtrip() { + unsafe { + let input = [1u8; 64]; + let mut output = [0u8; 64]; + + asm!( + "vmovups {zmm}, [{input}]", + "vmovups [{output}], {zmm}", + input = in(reg) input.as_ptr(), + output = in(reg) output.as_mut_ptr(), + zmm = out(zmm_reg) _, + ); + + assert_eq!(input, output); + } +} + fn test_checked_mul() { let u: Option = u8::from_str_radix("1000", 10).ok(); assert_eq!(u, None); @@ -614,3 +681,18 @@ fn map(a: Option<(u8, Box)>) -> Option> { Some((_, instr)) => Some(instr), } } + +// FIXME enable once inline asm sym references are stabilized in cg_clif +// #[cfg(target_arch = "x86_64")] +// fn inline_asm_call_custom_abi() { +// use std::arch::{asm, naked_asm}; +// +// #[unsafe(naked)] +// unsafe extern "custom" fn double() { +// naked_asm!("add rax, rax", "ret"); +// } +// +// let mut x: u64 = 21; +// unsafe { asm!("call {}", sym double, inout("rax") x) }; +// assert_eq!(x, 42); +// } diff --git a/patches/0027-stdlib-128bit-atomic-operations.patch b/patches/0027-stdlib-128bit-atomic-operations.patch index 38bb43f8204b4..b7276e43153bc 100644 --- a/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/patches/0027-stdlib-128bit-atomic-operations.patch @@ -37,16 +37,7 @@ diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index bf2b6d59f88..d5ccce03bbf 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -300,8 +300,6 @@ impl_atomic_primitive!(AtomicI32(i32), size("32"), align(4)); - impl_atomic_primitive!(AtomicU32(u32), size("32"), align(4)); - impl_atomic_primitive!(AtomicI64(i64), size("64"), align(8)); - impl_atomic_primitive!(AtomicU64(u64), size("64"), align(8)); --impl_atomic_primitive!(AtomicI128(i128), size("128"), align(16)); --impl_atomic_primitive!(AtomicU128(u128), size("128"), align(16)); - - #[cfg(target_pointer_width = "16")] - impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(2)); -@@ -3585,44 +3585,6 @@ pub const fn as_ptr(&self) -> *mut $int_type { +@@ -3585,42 +3585,6 @@ pub const fn as_ptr(&self) -> *mut $int_type { 8, u64 AtomicU64 } @@ -62,7 +53,6 @@ index bf2b6d59f88..d5ccce03bbf 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- rustc_diagnostic_item = "AtomicI128", - "i128", - "#![feature(integer_atomics)]\n\n", - atomic_min, atomic_max, @@ -81,7 +71,6 @@ index bf2b6d59f88..d5ccce03bbf 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- rustc_diagnostic_item = "AtomicU128", - "u128", - "#![feature(integer_atomics)]\n\n", - atomic_umin, atomic_umax, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fe967c84352c8..d4bb9bea82bb5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-02-18" +channel = "nightly-2026-03-25" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index bb9f69b5c9744..2ca0c3cab910f 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -63,18 +63,18 @@ index 2e16f2cf27..3ac3df99a8 100644 # Note that RUSTFLAGS_BOOTSTRAP should always be added to the end of # RUSTFLAGS, since that causes RUSTFLAGS_BOOTSTRAP to override RUSTFLAGS. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs -index a656927b1f6..44fc5546fac 100644 +index bc68bfe396..00143ef3ed 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs -@@ -2249,7 +2249,7 @@ pub fn parse_download_ci_llvm<'a>( - } +@@ -2230,7 +2230,7 @@ pub fn download_ci_rustc_commit<'a>( + return None; + } - #[cfg(not(test))] -- if b && dwn_ctx.is_running_on_ci && CiEnv::is_rust_lang_managed_ci_job() { -+ if false && dwn_ctx.is_running_on_ci && CiEnv::is_rust_lang_managed_ci_job() { - // On rust-lang CI, we must always rebuild LLVM if there were any modifications to it - panic!( - "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead." +- if dwn_ctx.is_running_on_ci() { ++ if false && dwn_ctx.is_running_on_ci() { + eprintln!("CI rustc commit matches with HEAD and we are in CI."); + eprintln!( + "\`rustc.download-ci\` functionality will be skipped as artifacts are not available." diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 330fb465de..a4593ed96f 100644 --- a/src/build_helper/src/git.rs diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 8712b41c8f8f6..71ff4eef071c3 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -20,7 +20,6 @@ for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|//@ error-pa done git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed -git checkout -- tests/ui/proc-macro/pretty-print-hack/ git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs # missing features @@ -152,7 +151,6 @@ rm -r tests/run-make/short-ice # ICE backtrace begin/end marker mismatch rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump 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/translation # same 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/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features diff --git a/src/global_asm.rs b/src/global_asm.rs index 1daf428acf766..b14988577845f 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -120,9 +120,15 @@ fn codegen_global_asm_inner<'tcx>( } let symbol = tcx.symbol_name(instance); + let symbol_name = if tcx.sess.target.is_like_darwin { + format!("_{}", symbol.name) + } else { + symbol.name.to_owned() + }; + // FIXME handle the case where the function was made private to the // current codegen unit - global_asm.push_str(&escape_symbol_name(tcx, symbol.name, span)); + global_asm.push_str(&escape_symbol_name(tcx, &symbol_name, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { if cfg!(not(feature = "inline_asm_sym")) { @@ -134,7 +140,13 @@ fn codegen_global_asm_inner<'tcx>( let instance = Instance::mono(tcx, def_id); let symbol = tcx.symbol_name(instance); - global_asm.push_str(&escape_symbol_name(tcx, symbol.name, span)); + let symbol_name = if tcx.sess.target.is_like_darwin { + format!("_{}", symbol.name) + } else { + symbol.name.to_owned() + }; + + global_asm.push_str(&escape_symbol_name(tcx, &symbol_name, span)); } } } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index ac0da06cbb8e3..8100d565b3974 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -3,8 +3,10 @@ use std::fmt::Write; use cranelift_codegen::isa::CallConv; +use rustc_abi::CanonAbi; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::LangItem; +use rustc_middle::ty::layout::FnAbiOf; use rustc_span::sym; use rustc_target::asm::*; use rustc_target::spec::Arch; @@ -120,21 +122,30 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( .unwrap(); let symbol = fx.tcx.symbol_name(instance); - // Pass a wrapper rather than the function itself as the function itself may not - // be exported from the main codegen unit and may thus be unreachable from the - // object file created by an external assembler. - let wrapper_name = format!( - "{}__inline_asm_{}_wrapper_n{}", - fx.symbol_name, - fx.cgu_name.as_str().replace('.', "__").replace('-', "_"), - fx.inline_asm_index, - ); - fx.inline_asm_index += 1; - let sig = - get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance); - create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name); - - CInlineAsmOperand::Symbol { symbol: wrapper_name } + if FullyMonomorphizedLayoutCx(fx.tcx) + .fn_abi_of_instance(instance, ty::List::empty()) + .conv + == CanonAbi::Custom + { + // We can't create a wrapper for custom ABI functions. + CInlineAsmOperand::Symbol { symbol: symbol.name.to_owned() } + } else { + // Pass a wrapper rather than the function itself as the function itself may not + // be exported from the main codegen unit and may thus be unreachable from the + // object file created by an external assembler. + let wrapper_name = format!( + "{}__inline_asm_{}_wrapper_n{}", + fx.symbol_name, + fx.cgu_name.as_str().replace('.', "__").replace('-', "_"), + fx.inline_asm_index, + ); + fx.inline_asm_index += 1; + let sig = + get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance); + create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name); + + CInlineAsmOperand::Symbol { symbol: wrapper_name } + } } else { span_bug!(span, "invalid type for asm sym (fn)"); } @@ -548,22 +559,21 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { match self.arch { InlineAsmArch::X86_64 => match reg { InlineAsmReg::X86(reg) - if reg as u32 >= X86InlineAsmReg::xmm0 as u32 - && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + if matches!( + reg.reg_class(), + X86InlineAsmRegClass::xmm_reg + | X86InlineAsmRegClass::ymm_reg + | X86InlineAsmRegClass::zmm_reg + ) => { - // rustc emits x0 rather than xmm0 - let class = match *modifier { - None | Some('x') => "xmm", - Some('y') => "ymm", - Some('z') => "zmm", - _ => unreachable!(), - }; - write!( - generated_asm, - "{class}{}", - reg as u32 - X86InlineAsmReg::xmm0 as u32 - ) - .unwrap(); + // rustc emits x0/y0/z0 rather than xmm0/ymm0/zmm0 + let name = reg.name(); + if let Some(prefix) = modifier { + let index = &name[3..]; + write!(generated_asm, "{prefix}mm{index}").unwrap(); + } else { + write!(generated_asm, "{name}").unwrap(); + } } _ => reg .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier) @@ -575,7 +585,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { CInlineAsmOperand::Const { ref value } => { generated_asm.push_str(value); } - CInlineAsmOperand::Symbol { ref symbol } => generated_asm.push_str(symbol), + CInlineAsmOperand::Symbol { ref symbol } => { + if binary_format == BinaryFormat::Macho { + generated_asm.push('_'); + } + + generated_asm.push_str(symbol); + } } } } @@ -716,12 +732,17 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { InlineAsmArch::X86_64 => { match reg { InlineAsmReg::X86(reg) - if reg as u32 >= X86InlineAsmReg::xmm0 as u32 - && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + if matches!( + reg.reg_class(), + X86InlineAsmRegClass::xmm_reg + | X86InlineAsmRegClass::ymm_reg + | X86InlineAsmRegClass::zmm_reg + ) => { - // rustc emits x0 rather than xmm0 - write!(generated_asm, " movups [rbx+0x{:x}], ", offset.bytes()).unwrap(); - write!(generated_asm, "xmm{}", reg as u32 - X86InlineAsmReg::xmm0 as u32) + // rustc emits x0/y0/z0 rather than xmm0/ymm0/zmm0 + let name = reg.name(); + let mov = if name.starts_with("xmm") { "movups" } else { "vmovups" }; + write!(generated_asm, " {mov} [rbx+0x{:x}], {name}", offset.bytes()) .unwrap(); } _ => { @@ -761,16 +782,17 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { InlineAsmArch::X86_64 => { match reg { InlineAsmReg::X86(reg) - if reg as u32 >= X86InlineAsmReg::xmm0 as u32 - && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + if matches!( + reg.reg_class(), + X86InlineAsmRegClass::xmm_reg + | X86InlineAsmRegClass::ymm_reg + | X86InlineAsmRegClass::zmm_reg + ) => { - // rustc emits x0 rather than xmm0 - write!( - generated_asm, - " movups xmm{}", - reg as u32 - X86InlineAsmReg::xmm0 as u32 - ) - .unwrap(); + // rustc emits x0/y0/z0 rather than xmm0/ymm0/zmm0 + let name = reg.name(); + let mov = if name.starts_with("xmm") { "movups" } else { "vmovups" }; + write!(generated_asm, " {mov} {name}").unwrap(); } _ => { generated_asm.push_str(" mov "); From 035bf6e39cd24b9232338ebd07fbf068fd809b7c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 26 Mar 2026 17:55:32 +0100 Subject: [PATCH 05/45] Update exclusion list in build_llvm_sysroot_for_triple --- build_system/build_sysroot.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 5205ec1e8aaa1..7185e8326237b 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -178,9 +178,7 @@ fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget { && !file_name_str.contains("rustc_std_workspace_") && !file_name_str.contains("rustc_demangle") && !file_name_str.contains("rustc_literal_escaper")) - || file_name_str.contains("chalk") - || file_name_str.contains("tracing") - || file_name_str.contains("regex") + || file_name_str.contains("LLVM") { // These are large crates that are part of the rustc-dev component and are not // necessary to run regular programs. From ea7f582d4e6e98d1a09f07dc4d8489099df883cc Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 26 Mar 2026 17:57:02 +0100 Subject: [PATCH 06/45] Use -Zbuild-dir-new-layout This will become the default soon. --- build_system/build_sysroot.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 7185e8326237b..216c87f095533 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -206,9 +206,9 @@ fn build_clif_sysroot_for_triple( apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs)); - // Cleanup the deps dir, but keep build scripts and the incremental cache for faster - // recompilation as they are not affected by changes in cg_clif. - ensure_empty_dir(&build_dir.join("deps")); + // Cleanup the build dir, but keep the incremental cache for faster + // recompilation as it is not affected by changes in cg_clif. + ensure_empty_dir(&build_dir.join("build")); } // Build sysroot @@ -241,6 +241,7 @@ fn build_clif_sysroot_for_triple( build_cmd.arg("--features").arg("backtrace panic-unwind"); build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display())); build_cmd.arg("-Zno-embed-metadata"); + 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.triple.contains("apple") { @@ -252,7 +253,13 @@ fn build_clif_sysroot_for_triple( } spawn_and_wait(build_cmd); - for entry in fs::read_dir(build_dir.join("deps")).unwrap() { + for entry in fs::read_dir(build_dir.join("build")) + .unwrap() + .flat_map(|entry| entry.unwrap().path().read_dir().unwrap()) + .map(|entry| entry.unwrap().path().join("out")) + .filter(|entry| entry.exists()) + .flat_map(|entry| entry.read_dir().unwrap()) + { let entry = entry.unwrap(); if let Some(ext) = entry.path().extension() { if ext == "d" || ext == "dSYM" || ext == "clif" { From 90b98b249da08be987caed58d43401d4a450f9b6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 31 Mar 2026 18:50:03 +1100 Subject: [PATCH 07/45] Use `Hcx`/`hcx` consistently for `StableHashingContext`. The `HashStable` and `ToStableHashKey` traits both have a type parameter that is sometimes called `CTX` and sometimes called `HCX`. (In practice this type parameter is always instantiated as `StableHashingContext`.) Similarly, variables with these types are sometimes called `ctx` and sometimes called `hcx`. This inconsistency has bugged me for some time. The `HCX`/`hcx` form is more informative (the `H`/`h` indicates what type of context it is) and it matches other cases like `tcx`, `dcx`, `icx`. Also, RFC 430 says that type parameters should have names that are "concise UpperCamelCase, usually single uppercase letter: T". In this case `H` feels insufficient, and `Hcx` feels better. Therefore, this commit changes the code to use `Hcx`/`hcx` everywhere. --- src/driver/aot.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 79a3214568082..b855e1fa4b780 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -45,8 +45,8 @@ enum OngoingModuleCodegen { Async(JoinHandle>), } -impl HashStable for OngoingModuleCodegen { - fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { +impl HashStable for OngoingModuleCodegen { + fn hash_stable(&self, _: &mut Hcx, _: &mut StableHasher) { // do nothing } } From 85e5a244a517a5cd72f7bd1ec0003be46a460887 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 17 Mar 2026 21:41:44 +1100 Subject: [PATCH 08/45] Use closures more consistently in `dep_graph.rs`. This file has several methods that take a `FnOnce() -> R` closure: - `DepGraph::with_ignore` - `DepGraph::with_query_deserialization` - `DepGraph::with_anon_task` - `DepGraphData::with_anon_task_inner` It also has two methods that take a faux closure via an `A` argument and a `fn(TyCtxt<'tcx>, A) -> R` argument: - DepGraph::with_task - DepGraphData::with_task The rationale is that the faux closure exercises tight control over what state they have access to. This seems silly when (a) they are passed a `TyCtxt`, and (b) when similar nearby functions take real closures. And they are more awkward to use, e.g. requiring multiple arguments to be gathered into a tuple. This commit changes the faux closures to real closures. --- src/driver/aot.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 79a3214568082..012d8caec16f8 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -380,11 +380,9 @@ fn codegen_cgu_content( fn module_codegen( tcx: TyCtxt<'_>, - (global_asm_config, cgu_name, token): ( - Arc, - rustc_span::Symbol, - ConcurrencyLimiterToken, - ), + global_asm_config: Arc, + cgu_name: rustc_span::Symbol, + token: ConcurrencyLimiterToken, ) -> OngoingModuleCodegen { let mut module = make_module(tcx.sess, cgu_name.as_str().to_string()); @@ -513,8 +511,14 @@ pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box { let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, - (global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())), - module_codegen, + || { + module_codegen( + tcx, + global_asm_config.clone(), + cgu.name(), + concurrency_limiter.acquire(tcx.dcx()), + ) + }, Some(rustc_middle::dep_graph::hash_result), ); IntoDynSyncSend(module) From adb7c3f538e0510a6cc434a2883d7679b014d891 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:52:35 +0200 Subject: [PATCH 09/45] Rustup to rustc 1.96.0-nightly (48cc71ee8 2026-03-31) --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d4bb9bea82bb5..2f0cfb79a2e51 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-03-25" +channel = "nightly-2026-04-01" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 29f956583deeb1f1f9e337ec492a961972014502 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 25 Mar 2026 08:54:32 +1100 Subject: [PATCH 10/45] Move `rustc_middle::mir::mono` to `rustc_middle::mono` Because the things in this module aren't MIR and don't use anything from `rustc_middle::mir`. Also, modules that use `mono` often don't use anything else from `rustc_middle::mir`. --- src/driver/aot.rs | 2 +- src/driver/mod.rs | 2 +- src/linkage.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index b855e1fa4b780..c74e0b9b1a669 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -19,7 +19,7 @@ use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_hir::attrs::Linkage as RLinkage; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility}; +use rustc_middle::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility}; use rustc_session::Session; use rustc_session::config::{OutputFilenames, OutputType}; diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 9f2b7b4b09f22..8d962aa1c7fba 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -6,7 +6,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::{MonoItem, MonoItemData}; +use rustc_middle::mono::{MonoItem, MonoItemData}; use crate::prelude::*; diff --git a/src/linkage.rs b/src/linkage.rs index d76ab9d0109f0..e373268d76b76 100644 --- a/src/linkage.rs +++ b/src/linkage.rs @@ -1,5 +1,5 @@ use rustc_hir::attrs::Linkage as RLinkage; -use rustc_middle::mir::mono::{MonoItem, Visibility}; +use rustc_middle::mono::{MonoItem, Visibility}; use crate::prelude::*; From 70ee124a0b3f2230a3676c5b54c295b5220e9970 Mon Sep 17 00:00:00 2001 From: Finchie Date: Fri, 10 Apr 2026 12:31:22 +0800 Subject: [PATCH 11/45] Call rustc assembler with `-Zunstable-options` This allows custom JSON targets to compile, as the assembler was previously failing with an error that `-Zunstable-options` had not been set. --- src/global_asm.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/global_asm.rs b/src/global_asm.rs index b14988577845f..5765601763e44 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -235,6 +235,9 @@ pub(crate) fn compile_global_asm( .arg("-") .arg("-Abad_asm_style") .arg("-Zcodegen-backend=llvm") + // JSON targets currently require `-Zunstable-options` + // Tracking issue: https://github.com/rust-lang/rust/issues/151528 + .arg("-Zunstable-options") .stdin(Stdio::piped()) .spawn() .expect("Failed to spawn `as`."); From d542d94602da86f579870b404cbcbbc0a460cffe Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 12 Apr 2026 21:52:34 +0200 Subject: [PATCH 12/45] Rustup to rustc 1.97.0-nightly (bf4fbfb7a 2026-04-11) --- rust-toolchain.toml | 2 +- src/driver/jit.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 2f0cfb79a2e51..8b80ca1810d44 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-04-01" +channel = "nightly-2026-04-12" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 9bbc338a8e07c..3903e6ea3b1da 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -7,7 +7,7 @@ use std::os::raw::{c_char, c_int}; use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::MonoItem; +use rustc_middle::mono::MonoItem; use rustc_session::Session; use rustc_session::config::OutputFilenames; use rustc_span::sym; From 86354453e582bbffb261ae9e6d6d7d7775cba9c7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 12 Apr 2026 21:52:50 +0200 Subject: [PATCH 13/45] Fix rustc test suite --- scripts/setup_rust_fork.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 2ca0c3cab910f..7ce54a45e2ce6 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -67,9 +67,9 @@ index bc68bfe396..00143ef3ed 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2230,7 +2230,7 @@ pub fn download_ci_rustc_commit<'a>( - return None; - } - + match freshness { + PathFreshness::LastModifiedUpstream { upstream } => upstream, + PathFreshness::HasLocalModifications { upstream, modifications } => { - if dwn_ctx.is_running_on_ci() { + if false && dwn_ctx.is_running_on_ci() { eprintln!("CI rustc commit matches with HEAD and we are in CI."); From a67de10494c49d76dce6aaaefc15da72cb58e053 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 8 Apr 2026 21:03:50 +0200 Subject: [PATCH 14/45] preseve SIMD element type information and provide it to LLVM for better optimization --- src/abi/pass_mode.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 44b63aa95f83c..0283263cc6047 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -26,7 +26,9 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam { (RegKind::Float, 4) => types::F32, (RegKind::Float, 8) => types::F64, (RegKind::Float, 16) => types::F128, - (RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(), + (RegKind::Vector { hint_vector_elem: _ }, size) => { + types::I8.by(u32::try_from(size).unwrap()).unwrap() + } _ => unreachable!("{:?}", reg), }; AbiParam::new(clif_ty) From 4fe5deaac71ed660be67229de6e5eb879b1df493 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 17 May 2025 14:35:25 +0000 Subject: [PATCH 15/45] Use `!null` pattern type in libcore --- example/mini_core.rs | 60 +++++++++++++++++++++++++++++--- example/mini_core_hello_world.rs | 23 ++++++++++-- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 218050982e6d3..ab9d2a743739f 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -8,6 +8,7 @@ rustc_attrs, rustc_private, transparent_unions, + pattern_types, auto_traits, freeze_impls )] @@ -15,6 +16,30 @@ #![no_core] #![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)] +#[lang = "pointee_trait"] +pub trait Pointee: PointeeSized { + #[lang = "metadata_type"] + // needed so that layout_of will return `TooGeneric` instead of `Unknown` + // when asked for the layout of `*const T`. Which is important for making + // transmutes between raw pointers (and especially pattern types of raw pointers) + // work. + type Metadata: Copy + Sync + Unpin + Freeze; +} + +#[lang = "dyn_metadata"] +pub struct DynMetadata { + _vtable_ptr: NonNull, + _phantom: PhantomData, +} + +unsafe extern "C" { + /// Opaque type for accessing vtables. + /// + /// Private implementation detail of `DynMetadata::size_of` etc. + /// There is conceptually not actually any Abstract Machine memory behind this pointer. + type VTable; +} + #[lang = "pointee_sized"] pub trait PointeeSized {} @@ -105,7 +130,7 @@ unsafe impl<'a, T: PointeeSized> Sync for &'a T {} unsafe impl Sync for [T; N] {} #[lang = "freeze"] -unsafe auto trait Freeze {} +pub unsafe auto trait Freeze {} unsafe impl Freeze for PhantomData {} unsafe impl Freeze for *const T {} @@ -570,10 +595,24 @@ pub trait Deref { fn deref(&self) -> &Self::Target; } +#[rustc_builtin_macro(pattern_type)] +#[macro_export] +macro_rules! pattern_type { + ($($arg:tt)*) => { + /* compiler built-in */ + }; +} + +impl CoerceUnsized for pattern_type!(*const T is !null) where + T: Unsize +{ +} + +impl, U> DispatchFromDyn for pattern_type!(T is !null) {} + #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] -pub struct NonNull(pub *const T); +pub struct NonNull(pub pattern_type!(*const T is !null)); impl CoerceUnsized> for NonNull where T: Unsize {} impl DispatchFromDyn> for NonNull where T: Unsize {} @@ -600,7 +639,16 @@ impl Box { let size = size_of::(); let ptr = libc::malloc(size); intrinsics::copy(&val as *const T as *const u8, ptr, size); - Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global) + Box( + Unique { + pointer: NonNull(intrinsics::transmute::< + *mut u8, + pattern_type!(*const T is !null), + >(ptr)), + _marker: PhantomData, + }, + Global, + ) } } } @@ -609,7 +657,9 @@ impl Drop for Box { fn drop(&mut self) { // inner value is dropped by compiler unsafe { - libc::free(self.0.pointer.0 as *mut u8); + libc::free(intrinsics::transmute::( + self.0.pointer.0, + ) as *mut u8); } } } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 6734d19fbb48b..5e986201b385c 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,4 +1,13 @@ -#![feature(no_core, lang_items, never_type, extern_types, thread_local, repr_simd, rustc_private)] +#![feature( + no_core, + lang_items, + never_type, + extern_types, + thread_local, + repr_simd, + pattern_types, + rustc_private +)] #![cfg_attr(not(any(jit, target_vendor = "apple", windows)), feature(linkage))] #![no_core] #![allow(dead_code, non_camel_case_types, internal_features)] @@ -153,7 +162,10 @@ extern "C" fn bool_struct_in_11(_arg0: bool_11) {} #[allow(unreachable_code)] // FIXME false positive fn main() { - take_unique(Unique { pointer: unsafe { NonNull(1 as *mut ()) }, _marker: PhantomData }); + take_unique(Unique { + pointer: unsafe { NonNull(intrinsics::transmute(1 as *mut ())) }, + _marker: PhantomData, + }); take_f32(0.1); call_return_u128_pair(); @@ -219,7 +231,12 @@ fn main() { let noisy_unsized_drop = const { intrinsics::needs_drop::() }; assert!(noisy_unsized_drop); - Unique { pointer: NonNull(1 as *mut &str), _marker: PhantomData } as Unique; + Unique { + pointer: NonNull(intrinsics::transmute::<_, pattern_type!(*const &str is !null)>( + 1 as *mut &str, + )), + _marker: PhantomData, + } as Unique; struct MyDst(T); From 438d886b84b90dd905c54c6bb94e4c56faf77310 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Tue, 14 Apr 2026 11:43:00 +0300 Subject: [PATCH 16/45] Lock stable_crate_ids once in create_crate_num --- compiler/rustc_middle/src/ty/context.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b908a6c6e8439..d439645d3542c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1411,12 +1411,12 @@ impl<'tcx> TyCtxt<'tcx> { self, stable_crate_id: StableCrateId, ) -> Result, CrateNum> { - if let Some(&existing) = self.untracked().stable_crate_ids.read().get(&stable_crate_id) { + let mut lock = self.untracked().stable_crate_ids.write(); + if let Some(&existing) = lock.get(&stable_crate_id) { return Err(existing); } - - let num = CrateNum::new(self.untracked().stable_crate_ids.read().len()); - self.untracked().stable_crate_ids.write().insert(stable_crate_id, num); + let num = CrateNum::new(lock.len()); + lock.insert(stable_crate_id, num); Ok(TyCtxtFeed { key: num, tcx: self }) } From c418fe72569012d93e511e90cc8305db3a74f07d Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 14 Apr 2026 11:35:26 -0700 Subject: [PATCH 17/45] `CValue::zst()` - add missing "ZST" in docs --- src/value_and_place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 5b76a4cb97793..9dc5012a602dc 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -98,7 +98,7 @@ impl<'tcx> CValue<'tcx> { /// Create an instance of a ZST /// - /// The is represented by a dangling pointer of suitable alignment. + /// The ZST is represented by a dangling pointer of suitable alignment. pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> { assert!(layout.is_zst()); CValue::by_ref(crate::Pointer::dangling(layout.align.abi), layout) From c08e62ab7734ce15341c843ca7513c75d72770d5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 15 Apr 2026 16:32:55 +0200 Subject: [PATCH 18/45] Rustup to rustc 1.97.0-nightly (a5c825cd8 2026-04-14) --- rust-toolchain.toml | 2 +- src/intrinsics/simd.rs | 139 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 127 insertions(+), 14 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8b80ca1810d44..7ec491b1b5dd9 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-04-12" +channel = "nightly-2026-04-15" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index cc2311a67b5d5..bb93926fd07b5 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -91,23 +91,26 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().icmp(IntCC::SignedGreaterThanOrEqual, x_lane, y_lane) } + // FIXME(bytecodealliance/wasmtime#8312): Replace with Cranelift + // `fcmp` once `f16`/`f128` backend lowerings have been added to + // Cranelift. (ty::Float(_), sym::simd_eq) => { - fx.bcx.ins().fcmp(FloatCC::Equal, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::Equal, x_lane, y_lane) } (ty::Float(_), sym::simd_ne) => { - fx.bcx.ins().fcmp(FloatCC::NotEqual, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::NotEqual, x_lane, y_lane) } (ty::Float(_), sym::simd_lt) => { - fx.bcx.ins().fcmp(FloatCC::LessThan, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::LessThan, x_lane, y_lane) } (ty::Float(_), sym::simd_le) => { - fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::LessThanOrEqual, x_lane, y_lane) } (ty::Float(_), sym::simd_gt) => { - fx.bcx.ins().fcmp(FloatCC::GreaterThan, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::GreaterThan, x_lane, y_lane) } (ty::Float(_), sym::simd_ge) => { - fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, x_lane, y_lane) + codegen_f16_f128::fcmp(fx, FloatCC::GreaterThanOrEqual, x_lane, y_lane) } _ => unreachable!(), @@ -391,6 +394,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( intrinsic, ) { (ty::Int(_), sym::simd_neg) => fx.bcx.ins().ineg(lane), + (ty::Float(FloatTy::F16), sym::simd_neg) => codegen_f16_f128::neg_f16(fx, lane), (ty::Float(_), sym::simd_neg) => fx.bcx.ins().fneg(lane), (ty::Uint(ty::UintTy::U8) | ty::Int(ty::IntTy::I8), sym::simd_bswap) => lane, @@ -418,7 +422,18 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // FIXME use vector instructions when possible simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { - match (lane_ty.kind(), intrinsic) { + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let (x_lane, y_lane) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + ( + codegen_f16_f128::f16_to_f32(fx, x_lane), + codegen_f16_f128::f16_to_f32(fx, y_lane), + ) + } else { + (x_lane, y_lane) + }; + + let res = match (lane_ty.kind(), intrinsic) { (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), @@ -435,6 +450,16 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), + (ty::Float(FloatTy::F16), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + // FIXME(bytecodealliance/wasmtime#8312): Already converted + // by the FIXME above. + // fx.bcx.ins().fpromote(types::F32, lhs), + // fx.bcx.ins().fpromote(types::F32, rhs), + &[x_lane, y_lane], + )[0], (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( "fmodf", vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], @@ -461,6 +486,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), _ => unreachable!(), + }; + + if *lane_ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res } }); } @@ -486,7 +520,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let b_lane = b.value_lane(fx, lane).load_scalar(fx); let c_lane = c.value_lane(fx, lane).load_scalar(fx); - let res_lane = fx.bcx.ins().fma(a_lane, b_lane, c_lane); + let res_lane = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + codegen_f16_f128::fma_f16(fx, a_lane, b_lane, c_lane) + } else { + fx.bcx.ins().fma(a_lane, b_lane, c_lane) + }; let res_lane = CValue::by_val(res_lane, res_lane_layout); ret.place_lane(fx, lane).write_cvalue(fx, res_lane); @@ -584,13 +622,28 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } - match intrinsic { + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let lane = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + codegen_f16_f128::f16_to_f32(fx, lane) + } else { + lane + }; + let res = match intrinsic { sym::simd_fabs => fx.bcx.ins().fabs(lane), sym::simd_fsqrt => fx.bcx.ins().sqrt(lane), sym::simd_ceil => fx.bcx.ins().ceil(lane), sym::simd_floor => fx.bcx.ins().floor(lane), sym::simd_trunc => fx.bcx.ins().trunc(lane), _ => unreachable!(), + }; + if *lane_ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res } }); } @@ -607,7 +660,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, Some(acc), ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fadd(a, b) + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) + } else { + (a, b) + }; + let res = fx.bcx.ins().fadd(a, b); + if *lane_ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res + } } else { fx.bcx.ins().iadd(a, b) } @@ -625,7 +693,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fadd(a, b) + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) + } else { + (a, b) + }; + let res = fx.bcx.ins().fadd(a, b); + if *lane_ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res + } } else { fx.bcx.ins().iadd(a, b) } @@ -644,7 +727,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, Some(acc), ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fmul(a, b) + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) + } else { + (a, b) + }; + let res = fx.bcx.ins().fmul(a, b); + if *lane_ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res + } } else { fx.bcx.ins().imul(a, b) } @@ -662,7 +760,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - fx.bcx.ins().fmul(a, b) + // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have + // been added to Cranelift. + let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { + (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) + } else { + (a, b) + }; + let res = fx.bcx.ins().fmul(a, b); + if *lane_ty.kind() == ty::Float(FloatTy::F16) { + // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift + // operation once Cranelift backend lowerings have been + // implemented. + codegen_f16_f128::f32_to_f16(fx, res) + } else { + res + } } else { fx.bcx.ins().imul(a, b) } From ff5d860e90ef7743ca914475f1a771f8e3960073 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 15 Apr 2026 16:50:08 +0200 Subject: [PATCH 19/45] Introduce helper functions for f16<->f32 casts when necessary --- src/codegen_f16_f128.rs | 34 ++++++ src/intrinsics/mod.rs | 18 ++-- src/intrinsics/simd.rs | 229 +++++++++++++--------------------------- src/num.rs | 23 ++-- 4 files changed, 120 insertions(+), 184 deletions(-) diff --git a/src/codegen_f16_f128.rs b/src/codegen_f16_f128.rs index d8977657e305d..e63e4bebf78a2 100644 --- a/src/codegen_f16_f128.rs +++ b/src/codegen_f16_f128.rs @@ -51,6 +51,40 @@ fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value { if ret_ty == types::I16 { fx.bcx.ins().bitcast(types::F16, MemFlags::new(), ret) } else { ret } } +// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have +// been added to Cranelift. +pub(crate) fn maybe_with_f16_to_f32( + fx: &mut FunctionCx<'_, '_, '_>, + val: Value, + f: impl FnOnce(&mut FunctionCx<'_, '_, '_>, Value) -> Value, +) -> Value { + if fx.bcx.func.dfg.value_type(val) == types::F16 { + let val = f16_to_f32(fx, val); + let res = f(fx, val); + f32_to_f16(fx, res) + } else { + f(fx, val) + } +} + +// FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have +// been added to Cranelift. +pub(crate) fn maybe_with_f16_to_f32_pair( + fx: &mut FunctionCx<'_, '_, '_>, + a: Value, + b: Value, + f: impl FnOnce(&mut FunctionCx<'_, '_, '_>, Value, Value) -> Value, +) -> Value { + if fx.bcx.func.dfg.value_type(a) == types::F16 { + let a = f16_to_f32(fx, a); + let b = f16_to_f32(fx, b); + let res = f(fx, a, b); + f32_to_f16(fx, res) + } else { + f(fx, a, b) + } +} + pub(crate) fn fcmp(fx: &mut FunctionCx<'_, '_, '_>, cc: FloatCC, lhs: Value, rhs: Value) -> Value { let ty = fx.bcx.func.dfg.value_type(lhs); match ty { diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 780550fc4cc74..95c47715d19df 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1197,12 +1197,9 @@ fn codegen_regular_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - // FIXME(bytecodealliance/wasmtime#8312): Use `fmin` directly once - // Cranelift backend lowerings are implemented. - let a = codegen_f16_f128::f16_to_f32(fx, a); - let b = codegen_f16_f128::f16_to_f32(fx, b); - let val = fx.bcx.ins().fmin(a, b); - let val = codegen_f16_f128::f32_to_f16(fx, val); + let val = codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmin(a, b) + }); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); ret.write_cvalue(fx, val); } @@ -1240,12 +1237,9 @@ fn codegen_regular_intrinsic_call<'tcx>( let a = a.load_scalar(fx); let b = b.load_scalar(fx); - // FIXME(bytecodealliance/wasmtime#8312): Use `fmax` directly once - // Cranelift backend lowerings are implemented. - let a = codegen_f16_f128::f16_to_f32(fx, a); - let b = codegen_f16_f128::f16_to_f32(fx, b); - let val = fx.bcx.ins().fmax(a, b); - let val = codegen_f16_f128::f32_to_f16(fx, val); + let val = codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmax(a, b) + }); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f16)); ret.write_cvalue(fx, val); } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index bb93926fd07b5..b8e1886b2d3c1 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -422,80 +422,65 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // FIXME use vector instructions when possible simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { - // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have - // been added to Cranelift. - let (x_lane, y_lane) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { - ( - codegen_f16_f128::f16_to_f32(fx, x_lane), - codegen_f16_f128::f16_to_f32(fx, y_lane), - ) - } else { - (x_lane, y_lane) - }; - - let res = match (lane_ty.kind(), intrinsic) { - (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), - (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), - - (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), - (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), - - (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), - (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), - (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), - (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), - (ty::Float(FloatTy::F16), sym::simd_rem) => fx.lib_call( - "fmodf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - // FIXME(bytecodealliance/wasmtime#8312): Already converted - // by the FIXME above. - // fx.bcx.ins().fpromote(types::F32, lhs), - // fx.bcx.ins().fpromote(types::F32, rhs), - &[x_lane, y_lane], - )[0], - (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( - "fmodf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - &[x_lane, y_lane], - )[0], - (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( - "fmod", - vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], - vec![AbiParam::new(types::F64)], - &[x_lane, y_lane], - )[0], - - (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), - (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), - (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - _ => unreachable!(), - }; - - if *lane_ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, res) - } else { - res - } + codegen_f16_f128::maybe_with_f16_to_f32_pair( + fx, + x_lane, + y_lane, + |fx, x_lane, y_lane| match (lane_ty.kind(), intrinsic) { + (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), + (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), + + (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), + (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), + + (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), + (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), + (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), + (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), + (ty::Float(FloatTy::F16), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + // FIXME(bytecodealliance/wasmtime#8312): Already converted + // by the FIXME above. + // fx.bcx.ins().fpromote(types::F32, lhs), + // fx.bcx.ins().fpromote(types::F32, rhs), + &[x_lane, y_lane], + )[0], + (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[x_lane, y_lane], + )[0], + (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( + "fmod", + vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], + vec![AbiParam::new(types::F64)], + &[x_lane, y_lane], + )[0], + + (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), + (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), + (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + _ => unreachable!(), + }, + ) }); } @@ -622,29 +607,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } - // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have - // been added to Cranelift. - let lane = if *lane_ty.kind() == ty::Float(FloatTy::F16) { - codegen_f16_f128::f16_to_f32(fx, lane) - } else { - lane - }; - let res = match intrinsic { + + codegen_f16_f128::maybe_with_f16_to_f32(fx, lane, |fx, lane| match intrinsic { sym::simd_fabs => fx.bcx.ins().fabs(lane), sym::simd_fsqrt => fx.bcx.ins().sqrt(lane), sym::simd_ceil => fx.bcx.ins().ceil(lane), sym::simd_floor => fx.bcx.ins().floor(lane), sym::simd_trunc => fx.bcx.ins().trunc(lane), _ => unreachable!(), - }; - if *lane_ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, res) - } else { - res - } + }) }); } @@ -660,22 +631,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, Some(acc), ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have - // been added to Cranelift. - let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { - (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) - } else { - (a, b) - }; - let res = fx.bcx.ins().fadd(a, b); - if *lane_ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, res) - } else { - res - } + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fadd(a, b) + }) } else { fx.bcx.ins().iadd(a, b) } @@ -693,22 +651,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have - // been added to Cranelift. - let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { - (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) - } else { - (a, b) - }; - let res = fx.bcx.ins().fadd(a, b); - if *lane_ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, res) - } else { - res - } + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fadd(a, b) + }) } else { fx.bcx.ins().iadd(a, b) } @@ -727,22 +672,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, Some(acc), ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have - // been added to Cranelift. - let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { - (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) - } else { - (a, b) - }; - let res = fx.bcx.ins().fmul(a, b); - if *lane_ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, res) - } else { - res - } + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmul(a, b) + }) } else { fx.bcx.ins().imul(a, b) } @@ -760,22 +692,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, lane_ty, a, b| { if lane_ty.is_floating_point() { - // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings have - // been added to Cranelift. - let (a, b) = if *lane_ty.kind() == ty::Float(FloatTy::F16) { - (codegen_f16_f128::f16_to_f32(fx, a), codegen_f16_f128::f16_to_f32(fx, b)) - } else { - (a, b) - }; - let res = fx.bcx.ins().fmul(a, b); - if *lane_ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, res) - } else { - res - } + codegen_f16_f128::maybe_with_f16_to_f32_pair(fx, a, b, |fx, a, b| { + fx.bcx.ins().fmul(a, b) + }) } else { fx.bcx.ins().imul(a, b) } diff --git a/src/num.rs b/src/num.rs index e583f3f2f754a..e533c0b631b01 100644 --- a/src/num.rs +++ b/src/num.rs @@ -358,7 +358,6 @@ pub(crate) fn codegen_float_binop<'tcx>( } else { (lhs, rhs) }; - let b = fx.bcx.ins(); let res = match bin_op { // FIXME(bytecodealliance/wasmtime#8312): Remove once backend lowerings // have been added to Cranelift. @@ -367,10 +366,10 @@ pub(crate) fn codegen_float_binop<'tcx>( { codegen_f16_f128::codegen_f128_binop(fx, bin_op, lhs, rhs) } - BinOp::Add => b.fadd(lhs, rhs), - BinOp::Sub => b.fsub(lhs, rhs), - BinOp::Mul => b.fmul(lhs, rhs), - BinOp::Div => b.fdiv(lhs, rhs), + BinOp::Add => fx.bcx.ins().fadd(lhs, rhs), + BinOp::Sub => fx.bcx.ins().fsub(lhs, rhs), + BinOp::Mul => fx.bcx.ins().fmul(lhs, rhs), + BinOp::Div => fx.bcx.ins().fdiv(lhs, rhs), BinOp::Rem => { let (name, ty, lhs, rhs) = match in_lhs.layout().ty.kind() { ty::Float(FloatTy::F16) => ( @@ -389,22 +388,12 @@ pub(crate) fn codegen_float_binop<'tcx>( _ => bug!(), }; - let ret_val = fx.lib_call( + fx.lib_call( name, vec![AbiParam::new(ty), AbiParam::new(ty)], vec![AbiParam::new(ty)], &[lhs, rhs], - )[0]; - - let ret_val = if *in_lhs.layout().ty.kind() == ty::Float(FloatTy::F16) { - // FIXME(bytecodealliance/wasmtime#8312): Use native Cranelift - // operation once Cranelift backend lowerings have been - // implemented. - codegen_f16_f128::f32_to_f16(fx, ret_val) - } else { - ret_val - }; - return CValue::by_val(ret_val, in_lhs.layout()); + )[0] } BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => { let fltcc = match bin_op { From 657259f645c88325eb94fe8b4000b4aeacb6a155 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 8 Apr 2026 15:01:26 +1000 Subject: [PATCH 20/45] Refactor FnDecl and FnSig flags into packed structs --- src/value_and_place.rs | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 9dc5012a602dc..67adbaf028eb9 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -870,20 +870,10 @@ pub(crate) fn assert_assignable<'tcx>( let from_sig = fx .tcx .normalize_erasing_late_bound_regions(fx.typing_env(), from_ty.fn_sig(fx.tcx)); - let FnSig { - inputs_and_output: types_from, - c_variadic: c_variadic_from, - safety: unsafety_from, - abi: abi_from, - } = from_sig; + let FnSig { inputs_and_output: types_from, fn_sig_kind: fn_sig_kind_from } = from_sig; let to_sig = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to_ty.fn_sig(fx.tcx)); - let FnSig { - inputs_and_output: types_to, - c_variadic: c_variadic_to, - safety: unsafety_to, - abi: abi_to, - } = to_sig; + let FnSig { inputs_and_output: types_to, fn_sig_kind: fn_sig_kind_to } = to_sig; let mut types_from = types_from.iter(); let mut types_to = types_to.iter(); loop { @@ -894,17 +884,7 @@ pub(crate) fn assert_assignable<'tcx>( } } assert_eq!( - c_variadic_from, c_variadic_to, - "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}", - from_sig, to_sig, fx, - ); - assert_eq!( - unsafety_from, unsafety_to, - "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}", - from_sig, to_sig, fx, - ); - assert_eq!( - abi_from, abi_to, + fn_sig_kind_from, fn_sig_kind_to, "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}", from_sig, to_sig, fx, ); From 644a946d85d88ee79ea571b74141cfbe0e3fe10f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 16 Apr 2026 16:03:16 +0200 Subject: [PATCH 21/45] Disable f16 portable-simd tests on x86_64-pc-windows-gnu It is currently broken on x86_64-pc-windows-gnu --- ...d-Disable-f16-usage-in-portable-simd.patch | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch diff --git a/patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch b/patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch new file mode 100644 index 0000000000000..029e493227cd1 --- /dev/null +++ b/patches/0001-portable-simd-Disable-f16-usage-in-portable-simd.patch @@ -0,0 +1,266 @@ +From 2aa88b261ffb51d3f18a4b9d3b79232d7445e5f3 Mon Sep 17 00:00:00 2001 +From: bjorn3 <17426603+bjorn3@users.noreply.github.com> +Date: Thu, 16 Apr 2026 17:29:02 +0200 +Subject: [PATCH] Disable f16 usage in portable-simd + +It is currently broken on x86_64-pc-windows-gnu +--- + Cargo.toml | 8 ++------ + crates/core_simd/src/alias.rs | 10 ---------- + crates/core_simd/src/cast.rs | 3 --- + crates/core_simd/src/lib.rs | 1 - + crates/core_simd/src/ops.rs | 2 +- + crates/core_simd/src/ops/unary.rs | 2 -- + crates/core_simd/src/simd/cmp/eq.rs | 2 +- + crates/core_simd/src/simd/cmp/ord.rs | 2 +- + crates/core_simd/src/simd/num/float.rs | 2 +- + crates/core_simd/src/vector.rs | 7 ------- + crates/core_simd/tests/f16_ops.rs | 10 ---------- + crates/std_float/src/lib.rs | 9 --------- + crates/test_helpers/src/biteq.rs | 2 +- + crates/test_helpers/src/lib.rs | 2 -- + crates/test_helpers/src/subnormals.rs | 2 +- + 15 files changed, 8 insertions(+), 56 deletions(-) + delete mode 100644 crates/core_simd/tests/f16_ops.rs + +diff --git a/Cargo.toml b/Cargo.toml +index 883140b..45296b4 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -1,10 +1,6 @@ + [workspace] + resolver = "1" +-members = [ +- "crates/core_simd", +- "crates/std_float", +- "crates/test_helpers", +-] ++members = ["crates/core_simd", "crates/std_float", "crates/test_helpers"] + + [profile.test.package."*"] + opt-level = 2 +@@ -15,4 +11,4 @@ opt-level = 2 + [workspace.dependencies.proptest] + version = "1.11" + default-features = false +-features = ["alloc", "f16"] ++features = ["alloc"] +diff --git a/crates/core_simd/src/alias.rs b/crates/core_simd/src/alias.rs +index 6dcfcb6..23f121c 100644 +--- a/crates/core_simd/src/alias.rs ++++ b/crates/core_simd/src/alias.rs +@@ -153,16 +153,6 @@ alias! { + usizex64 64 + } + +- f16 = { +- f16x1 1 +- f16x2 2 +- f16x4 4 +- f16x8 8 +- f16x16 16 +- f16x32 32 +- f16x64 64 +- } +- + f32 = { + f32x1 1 + f32x2 2 +diff --git a/crates/core_simd/src/cast.rs b/crates/core_simd/src/cast.rs +index 69dc7ba..1c3592f 100644 +--- a/crates/core_simd/src/cast.rs ++++ b/crates/core_simd/src/cast.rs +@@ -44,9 +44,6 @@ impl SimdCast for u64 {} + unsafe impl Sealed for usize {} + impl SimdCast for usize {} + // Safety: primitive number types can be cast to other primitive number types +-unsafe impl Sealed for f16 {} +-impl SimdCast for f16 {} +-// Safety: primitive number types can be cast to other primitive number types + unsafe impl Sealed for f32 {} + impl SimdCast for f32 {} + // Safety: primitive number types can be cast to other primitive number types +diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs +index 413a886..115be44 100644 +--- a/crates/core_simd/src/lib.rs ++++ b/crates/core_simd/src/lib.rs +@@ -1,7 +1,6 @@ + #![no_std] + #![feature( + convert_float_to_int, +- f16, + core_intrinsics, + decl_macro, + repr_simd, +diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs +index c0a06ed..eb6601f 100644 +--- a/crates/core_simd/src/ops.rs ++++ b/crates/core_simd/src/ops.rs +@@ -245,7 +245,7 @@ for_base_ops! { + // We don't need any special precautions here: + // Floats always accept arithmetic ops, but may become NaN. + for_base_ops! { +- T = (f16, f32, f64); ++ T = (f32, f64); + type Lhs = Simd; + type Rhs = Simd; + type Output = Self; +diff --git a/crates/core_simd/src/ops/unary.rs b/crates/core_simd/src/ops/unary.rs +index af7aa8a..e1c0616 100644 +--- a/crates/core_simd/src/ops/unary.rs ++++ b/crates/core_simd/src/ops/unary.rs +@@ -19,8 +19,6 @@ macro_rules! neg { + } + + neg! { +- impl Neg for Simd +- + impl Neg for Simd + + impl Neg for Simd +diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs +index 7683640..d553d6c 100644 +--- a/crates/core_simd/src/simd/cmp/eq.rs ++++ b/crates/core_simd/src/simd/cmp/eq.rs +@@ -42,7 +42,7 @@ macro_rules! impl_number { + } + } + +-impl_number! { f16, f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } ++impl_number! { f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize } + + macro_rules! impl_mask { + { $($integer:ty),* } => { +diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs +index 5a4e74c..5672fbb 100644 +--- a/crates/core_simd/src/simd/cmp/ord.rs ++++ b/crates/core_simd/src/simd/cmp/ord.rs +@@ -144,7 +144,7 @@ macro_rules! impl_float { + } + } + +-impl_float! { f16, f32, f64 } ++impl_float! { f32, f64 } + + macro_rules! impl_mask { + { $($integer:ty),* } => { +diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs +index 510f4c9..175cbce 100644 +--- a/crates/core_simd/src/simd/num/float.rs ++++ b/crates/core_simd/src/simd/num/float.rs +@@ -444,4 +444,4 @@ macro_rules! impl_trait { + } + } + +-impl_trait! { f16 { bits: u16, mask: i16 }, f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } } ++impl_trait! { f32 { bits: u32, mask: i32 }, f64 { bits: u64, mask: i64 } } +diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs +index fbef69f..c8e0b8c 100644 +--- a/crates/core_simd/src/vector.rs ++++ b/crates/core_simd/src/vector.rs +@@ -1146,13 +1146,6 @@ unsafe impl SimdElement for isize { + type Mask = isize; + } + +-impl Sealed for f16 {} +- +-// Safety: f16 is a valid SIMD element type, and is supported by this API +-unsafe impl SimdElement for f16 { +- type Mask = i16; +-} +- + impl Sealed for f32 {} + + // Safety: f32 is a valid SIMD element type, and is supported by this API +diff --git a/crates/core_simd/tests/f16_ops.rs b/crates/core_simd/tests/f16_ops.rs +deleted file mode 100644 +index f89bdf4..0000000 +--- a/crates/core_simd/tests/f16_ops.rs ++++ /dev/null +@@ -1,10 +0,0 @@ +-#![feature(portable_simd)] +-#![feature(f16)] +- +-#[macro_use] +-mod ops_macros; +- +-// FIXME: some f16 operations cause rustc to hang on wasm simd +-// https://github.com/llvm/llvm-project/issues/189251 +-#[cfg(not(all(target_arch = "wasm32", target_feature = "simd128")))] +-impl_float_tests! { f16, i16 } +diff --git a/crates/std_float/src/lib.rs b/crates/std_float/src/lib.rs +index ff35254..acc1bfc 100644 +--- a/crates/std_float/src/lib.rs ++++ b/crates/std_float/src/lib.rs +@@ -2,7 +2,6 @@ + feature = "as_crate", + feature(core_intrinsics), + feature(portable_simd), +- feature(f16), + allow(internal_features) + )] + #[cfg(not(feature = "as_crate"))] +@@ -170,17 +169,9 @@ pub trait StdFloat: Sealed + Sized { + fn fract(self) -> Self; + } + +-impl Sealed for Simd {} + impl Sealed for Simd {} + impl Sealed for Simd {} + +-impl StdFloat for Simd { +- #[inline] +- fn fract(self) -> Self { +- self - self.trunc() +- } +-} +- + impl StdFloat for Simd { + #[inline] + fn fract(self) -> Self { +diff --git a/crates/test_helpers/src/biteq.rs b/crates/test_helpers/src/biteq.rs +index 36761e3..cbc20cd 100644 +--- a/crates/test_helpers/src/biteq.rs ++++ b/crates/test_helpers/src/biteq.rs +@@ -53,7 +53,7 @@ macro_rules! impl_float_biteq { + }; + } + +-impl_float_biteq! { f16, f32, f64 } ++impl_float_biteq! { f32, f64 } + + impl BitEq for *const T { + fn biteq(&self, other: &Self) -> bool { +diff --git a/crates/test_helpers/src/lib.rs b/crates/test_helpers/src/lib.rs +index 82adb06..4b03674 100644 +--- a/crates/test_helpers/src/lib.rs ++++ b/crates/test_helpers/src/lib.rs +@@ -1,4 +1,3 @@ +-#![feature(f16)] + #![cfg_attr( + any(target_arch = "powerpc", target_arch = "powerpc64"), + feature(powerpc_target_feature, stdarch_powerpc) +@@ -47,7 +46,6 @@ impl_num! { u16 } + impl_num! { u32 } + impl_num! { u64 } + impl_num! { usize } +-impl_num! { f16 } + impl_num! { f32 } + impl_num! { f64 } + +diff --git a/crates/test_helpers/src/subnormals.rs b/crates/test_helpers/src/subnormals.rs +index 44dfbb3..b5f19ba 100644 +--- a/crates/test_helpers/src/subnormals.rs ++++ b/crates/test_helpers/src/subnormals.rs +@@ -39,7 +39,7 @@ macro_rules! impl_else { + } + } + +-impl_float! { f16, f32, f64 } ++impl_float! { f32, f64 } + impl_else! { i8, i16, i32, i64, isize, u8, u16, u32, u64, usize } + + /// AltiVec should flush subnormal inputs to zero, but QEMU seems to only flush outputs. +-- +2.53.0 + From 0afeef0f0de531f978c105bc590a097884a6e4b5 Mon Sep 17 00:00:00 2001 From: Rudraksh Joshi <127816064+0xmuon@users.noreply.github.com> Date: Thu, 16 Apr 2026 16:27:18 +0530 Subject: [PATCH 22/45] fail loudly on unsized by-ref invariants (rust-lang/rustc_codegen_cranelift#1644) replace the remaining todo!() paths for unsized by-ref values in src/value_and_place.rs with explicit bug!() failures. This makes invariant violations fail loudly instead of panicking via unfinished code paths,and without claiming support for unsized by-ref handling that is not actually implemented. --- src/value_and_place.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 5b76a4cb97793..e6d723a954436 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -204,7 +204,9 @@ impl<'tcx> CValue<'tcx> { let (field_ptr, field_layout) = codegen_field(fx, ptr, None, layout, field); CValue::by_ref(field_ptr, field_layout) } - CValueInner::ByRef(_, Some(_)) => todo!(), + CValueInner::ByRef(_, Some(_)) => { + bug!("value_field for unsized by-ref value not supported") + } } } @@ -655,7 +657,13 @@ impl<'tcx> CPlace<'tcx> { flags, ); } - CValueInner::ByRef(_, Some(_)) => todo!(), + CValueInner::ByRef(_from_ptr, Some(_extra)) => { + bug!( + "write_cvalue for unsized by-ref value not allowed: dst={:?} src={:?}", + dst_layout.ty, + from.layout().ty + ); + } } } } From 973ab0a729022a5156588f2064099d855283c4a9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:33:00 +0200 Subject: [PATCH 23/45] Rustup to rustc 1.97.0-nightly (7af3402cd 2026-04-16) --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 7ec491b1b5dd9..bf1db0c1b9ea7 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-04-15" +channel = "nightly-2026-04-17" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 8591f0f230c44830c16817d8e67c3dc655dfb050 Mon Sep 17 00:00:00 2001 From: Kao-Wei Yeh Date: Wed, 25 Mar 2026 00:13:33 +0800 Subject: [PATCH 24/45] Tweak irrefutable let else warning output, add new suggestion --- compiler/rustc_mir_build/src/errors.rs | 32 +++---- .../src/thir/pattern/check_match.rs | 71 +++++++++++++-- .../let-else/let-else-irrefutable-152938.rs | 2 +- .../let-else-irrefutable-152938.stderr | 18 ++-- tests/ui/let-else/let-else-irrefutable.rs | 12 ++- tests/ui/let-else/let-else-irrefutable.stderr | 47 +++++----- tests/ui/parser/bad-let-else-statement.rs | 16 ++-- tests/ui/parser/bad-let-else-statement.stderr | 89 ++++++------------- tests/ui/span/let-offset-of.rs | 2 +- tests/ui/span/let-offset-of.stderr | 13 ++- 10 files changed, 170 insertions(+), 132 deletions(-) diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 793d9ef18eb61..b7f4fc093b6ba 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -924,22 +924,24 @@ pub(crate) struct IrrefutableLetPatternsIfLetGuard { } #[derive(Diagnostic)] -#[diag( - "irrefutable `let...else` {$count -> - [one] pattern - *[other] patterns -}" -)] -#[note( - "{$count -> - [one] this pattern always matches, so the else clause is unreachable - *[other] these patterns always match, so the else clause is unreachable -}" -)] +#[diag("unreachable `else` clause")] +#[note("this pattern always matches, so the else clause is unreachable")] pub(crate) struct IrrefutableLetPatternsLetElse { - pub(crate) count: usize, - #[help("remove this `else` block")] - pub(crate) else_span: Option, + #[subdiagnostic] + pub(crate) be_replaced: Option, +} + +#[derive(Subdiagnostic, Debug)] +#[suggestion( + "consider using `let {$lhs} = {$rhs}` to match on a specific variant", + code = "let {lhs} = {rhs}", + applicability = "machine-applicable" +)] +pub(crate) struct LetElseReplacementSuggestion { + #[primary_span] + pub(crate) span: Span, + pub(crate) lhs: String, + pub(crate) rhs: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index baabc1afe3fac..3888a297c891c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -168,7 +168,7 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return }; // Lint only single irrefutable let binding. if let [Some((_, Irrefutable))] = chain_refutabilities[..] { - self.lint_single_let(ex.span, None); + self.lint_single_let(ex.span, None, None); } return; } @@ -438,7 +438,45 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { if let LetSource::PlainLet = self.let_source { self.check_binding_is_irrefutable(pat, "local binding", scrut, Some(span)); } else if let Ok(Irrefutable) = self.is_let_irrefutable(pat, scrut) { - self.lint_single_let(span, else_span); + if span.from_expansion() { + self.lint_single_let(span, None, None); + return; + } + let let_else_span = self.check_irrefutable_option_some(pat, scrut, span); + + let sm = self.tcx.sess.source_map(); + let next_token_start = sm.span_extend_while_whitespace(span.clone()).hi(); + let line_span = sm.span_extend_to_line(span.clone()).with_lo(next_token_start); + let else_keyword_span = sm.span_until_whitespace(line_span); + self.lint_single_let(span, Some(else_keyword_span), let_else_span); + } + } + + /// Check case `let x = Some(y);`, user likely intended to destructure `Option` + fn check_irrefutable_option_some( + &self, + pat: &'p Pat<'tcx>, + initializer: Option<&Expr<'tcx>>, + span: Span, + ) -> Option { + if let sm = self.tcx.sess.source_map() + && let Some(initializer) = initializer + && let Some(s_ty) = initializer.ty.ty_adt_def() + && self.tcx.is_diagnostic_item(rustc_span::sym::Option, s_ty.did()) + && let ExprKind::Scope { value, .. } = initializer.kind + && let initializer_expr = &self.thir[value] + && let ExprKind::Adt(box AdtExpr { fields, .. }) = &initializer_expr.kind + && let Some(field) = fields.first() + && let inner = &self.thir[field.expr] + && let Some(inner_ty) = inner.ty.ty_adt_def() + && self.tcx.is_diagnostic_item(rustc_span::sym::Option, inner_ty.did()) + && let Ok(rhs) = sm.span_to_snippet(inner.span) + && let Ok(lhs) = sm.span_to_snippet(pat.span) + { + let lhs = format!("Some({})", lhs); + Some(LetElseReplacementSuggestion { span, lhs, rhs }) + } else { + None } } @@ -546,14 +584,20 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { } #[instrument(level = "trace", skip(self))] - fn lint_single_let(&mut self, let_span: Span, else_span: Option) { + fn lint_single_let( + &mut self, + let_span: Span, + else_keyword_span: Option, + let_else_span: Option, + ) { report_irrefutable_let_patterns( self.tcx, self.hir_source, self.let_source, 1, let_span, - else_span, + else_keyword_span, + let_else_span, ); } @@ -849,7 +893,8 @@ fn report_irrefutable_let_patterns( source: LetSource, count: usize, span: Span, - else_span: Option, + else_keyword_span: Option, + let_else_span: Option, ) { macro_rules! emit_diag { ($lint:tt) => {{ @@ -862,11 +907,23 @@ fn report_irrefutable_let_patterns( LetSource::IfLet | LetSource::ElseIfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => { + let spans = match else_keyword_span { + Some(else_keyword_span) => { + let mut spans = MultiSpan::from_span(else_keyword_span); + spans.push_span_label( + span, + msg!("assigning to binding pattern will always succeed"), + ); + spans + } + None => span.into(), + }; + tcx.emit_node_span_lint( IRREFUTABLE_LET_PATTERNS, id, - span, - IrrefutableLetPatternsLetElse { count, else_span }, + spans, + IrrefutableLetPatternsLetElse { be_replaced: let_else_span }, ); } LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), diff --git a/tests/ui/let-else/let-else-irrefutable-152938.rs b/tests/ui/let-else/let-else-irrefutable-152938.rs index 6e0ffe3fb8706..25e3e0f6e5708 100644 --- a/tests/ui/let-else/let-else-irrefutable-152938.rs +++ b/tests/ui/let-else/let-else-irrefutable-152938.rs @@ -6,7 +6,7 @@ pub fn say_hello(name: Option) { let name_str = Some(name) else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause drop(name_str); } diff --git a/tests/ui/let-else/let-else-irrefutable-152938.stderr b/tests/ui/let-else/let-else-irrefutable-152938.stderr index 57632964be9b3..e32f4960a3350 100644 --- a/tests/ui/let-else/let-else-irrefutable-152938.stderr +++ b/tests/ui/let-else/let-else-irrefutable-152938.stderr @@ -1,16 +1,18 @@ -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable-152938.rs:8:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable-152938.rs:8:31 | LL | let name_str = Some(name) else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable-152938.rs:8:36 - | -LL | let name_str = Some(name) else { return; }; - | ^^^^^^^^^^^ = note: `#[warn(irrefutable_let_patterns)]` on by default +help: consider using `let Some(name_str) = name` to match on a specific variant + | +LL - let name_str = Some(name) else { return; }; +LL + let Some(name_str) = name else { return; }; + | warning: 1 warning emitted diff --git a/tests/ui/let-else/let-else-irrefutable.rs b/tests/ui/let-else/let-else-irrefutable.rs index f9675ff5938eb..59de726d38ddf 100644 --- a/tests/ui/let-else/let-else-irrefutable.rs +++ b/tests/ui/let-else/let-else-irrefutable.rs @@ -1,10 +1,18 @@ //@ check-pass fn main() { - let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern + let x = 1 else { return }; //~ WARN unreachable `else` clause // Multiline else blocks should not get printed - let x = 1 else { //~ WARN irrefutable `let...else` pattern + let x = 1 else { //~ WARN unreachable `else` clause + eprintln!("problem case encountered"); + return + }; + + let case = Some("a"); + let name = Some(case) else { + //~^ WARN unreachable `else` clause + //~| HELP consider using `let Some(name) = case` to match on a specific variant eprintln!("problem case encountered"); return }; diff --git a/tests/ui/let-else/let-else-irrefutable.stderr b/tests/ui/let-else/let-else-irrefutable.stderr index d36d227b4156a..12338789d2a03 100644 --- a/tests/ui/let-else/let-else-irrefutable.stderr +++ b/tests/ui/let-else/let-else-irrefutable.stderr @@ -1,33 +1,38 @@ -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable.rs:4:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:4:15 | LL | let x = 1 else { return }; - | ^^^^^^^^^ + | --------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable.rs:4:20 - | -LL | let x = 1 else { return }; - | ^^^^^^^^^^ = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/let-else-irrefutable.rs:7:5 +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:7:15 | LL | let x = 1 else { - | ^^^^^^^^^ + | --------- ^^^^ + | | + | assigning to binding pattern will always succeed + | + = note: this pattern always matches, so the else clause is unreachable + +warning: unreachable `else` clause + --> $DIR/let-else-irrefutable.rs:13:27 + | +LL | let name = Some(case) else { + | --------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-else-irrefutable.rs:7:20 - | -LL | let x = 1 else { - | ____________________^ -LL | | eprintln!("problem case encountered"); -LL | | return -LL | | }; - | |_____^ +help: consider using `let Some(name) = case` to match on a specific variant + | +LL - let name = Some(case) else { +LL + let Some(name) = case else { + | -warning: 2 warnings emitted +warning: 3 warnings emitted diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index 3ede26dbcd06c..a552fbcfc1fc3 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -93,10 +93,10 @@ fn i() { fn j() { let mut bar = 0; let foo = bar = { - //~^ WARN irrefutable `let...else` pattern 1 } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } @@ -158,21 +158,21 @@ fn o() -> Result<(), ()> { fn q() { let foo = |x: i32| { - //~^ WARN irrefutable `let...else` pattern x } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn r() { let ok = format_args!("") else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause let bad = format_args! {""} else { return; }; //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed - //~| WARN irrefutable `let...else` pattern + //~| WARN unreachable `else` clause } fn s() { @@ -202,10 +202,10 @@ fn t() { } let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { - //~^ WARN irrefutable `let...else` pattern 8 } else { - //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~^ WARN unreachable `else` clause + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 8545d95f507f6..76fbbbb8c1e10 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -125,7 +125,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:98:5 + --> $DIR/bad-let-else-statement.rs:97:5 | LL | } else { | ^ @@ -133,7 +133,6 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = bar = ({ -LL | LL | 1 LL ~ }) else { | @@ -204,7 +203,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:163:5 + --> $DIR/bad-let-else-statement.rs:162:5 | LL | } else { | ^ @@ -212,7 +211,6 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = |x: i32| ({ -LL | LL | x LL ~ }) else { | @@ -230,7 +228,7 @@ LL + let bad = format_args! ("") else { return; }; | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:207:5 + --> $DIR/bad-let-else-statement.rs:206:5 | LL | } else { | ^ @@ -238,7 +236,6 @@ LL | } else { help: use parentheses instead of braces for this macro | LL ~ let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! ( -LL | LL | 8 LL ~ ) else { | @@ -259,92 +256,62 @@ LL - let 0 = a! {} else { return; }; LL + let 0 = a! () else { return; }; | -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:95:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:97:7 | LL | / let foo = bar = { -LL | | LL | | 1 LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:98:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:160:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:162:7 | LL | / let foo = |x: i32| { -LL | | LL | | x LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:163:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:170:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:170:31 | LL | let ok = format_args!("") else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:170:36 - | -LL | let ok = format_args!("") else { return; }; - | ^^^^^^^^^^^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:173:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:173:33 | LL | let bad = format_args! {""} else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------- ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:173:38 - | -LL | let bad = format_args! {""} else { return; }; - | ^^^^^^^^^^^ -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:204:5 +warning: unreachable `else` clause + --> $DIR/bad-let-else-statement.rs:206:7 | LL | / let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { -LL | | LL | | 8 LL | | } else { - | |_____^ + | | - ^^^^ + | |_____| + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/bad-let-else-statement.rs:207:12 - | -LL | } else { - | ____________^ -LL | | -LL | | return; -LL | | }; - | |_____^ error: aborting due to 19 previous errors; 5 warnings emitted diff --git a/tests/ui/span/let-offset-of.rs b/tests/ui/span/let-offset-of.rs index 99b34a1928470..eeecf38e6b6a9 100644 --- a/tests/ui/span/let-offset-of.rs +++ b/tests/ui/span/let-offset-of.rs @@ -15,5 +15,5 @@ fn init_to_offset_of() { //~^ WARN irrefutable `if let` pattern let x = offset_of!(Foo, field) else { return; }; - //~^ WARN irrefutable `let...else` pattern + //~^ WARN unreachable `else` clause } diff --git a/tests/ui/span/let-offset-of.stderr b/tests/ui/span/let-offset-of.stderr index df9b1e695b1e4..afcf8a8103d9d 100644 --- a/tests/ui/span/let-offset-of.stderr +++ b/tests/ui/span/let-offset-of.stderr @@ -8,18 +8,15 @@ LL | if let x = offset_of!(Foo, field) {} = help: consider replacing the `if let` with a `let` = note: `#[warn(irrefutable_let_patterns)]` on by default -warning: irrefutable `let...else` pattern - --> $DIR/let-offset-of.rs:17:5 +warning: unreachable `else` clause + --> $DIR/let-offset-of.rs:17:36 | LL | let x = offset_of!(Foo, field) else { return; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------ ^^^^ + | | + | assigning to binding pattern will always succeed | = note: this pattern always matches, so the else clause is unreachable -help: remove this `else` block - --> $DIR/let-offset-of.rs:17:41 - | -LL | let x = offset_of!(Foo, field) else { return; }; - | ^^^^^^^^^^^ warning: 2 warnings emitted From 3d2e5934dd8c2c48f68ffc5ea2109e50e36d40f8 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Wed, 15 Apr 2026 12:17:20 +0800 Subject: [PATCH 25/45] fix all errors --- src/debuginfo/mod.rs | 6 +++++- src/main_shim.rs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 756f86a7d0111..6ab5c5088e55a 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -19,6 +19,7 @@ use indexmap::IndexSet; use rustc_codegen_ssa::debuginfo::type_names; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefIdMap; +use rustc_middle::ty::Unnormalized; use rustc_session::Session; use rustc_session::config::DebugInfo; use rustc_span::{RemapPathScopeComponents, SourceFileHash, StableSourceFileId}; @@ -244,7 +245,10 @@ impl DebugContext { type_names::push_generic_args( tcx, - tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args), + tcx.normalize_erasing_regions( + ty::TypingEnv::fully_monomorphized(), + Unnormalized::new_wip(args), + ), &mut name, ); diff --git a/src/main_shim.rs b/src/main_shim.rs index c3e4bf1f0c275..dd776f9cfcaee 100644 --- a/src/main_shim.rs +++ b/src/main_shim.rs @@ -1,6 +1,6 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use rustc_hir::LangItem; -use rustc_middle::ty::{AssocTag, GenericArg}; +use rustc_middle::ty::{AssocTag, GenericArg, Unnormalized}; use rustc_session::config::EntryFnType; use rustc_span::{DUMMY_SP, Ident}; @@ -50,7 +50,7 @@ pub(crate) fn maybe_create_entry_wrapper( // listing. let main_ret_ty = tcx.normalize_erasing_regions( ty::TypingEnv::fully_monomorphized(), - main_ret_ty.no_bound_vars().unwrap(), + Unnormalized::new_wip(main_ret_ty.no_bound_vars().unwrap()), ); let cmain_sig = Signature { From af2b606baa384f7488d9d9e29639550a7a095575 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:46:07 +0200 Subject: [PATCH 26/45] Rustup to rustc 1.97.0-nightly (e22c616e4 2026-04-19) --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index bf1db0c1b9ea7..42db240bc4f86 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-04-17" +channel = "nightly-2026-04-20" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 720aed373a6e31583c10681384a06143c5d64a95 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 20 Apr 2026 15:09:48 +0200 Subject: [PATCH 27/45] 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 71ff4eef071c3..0b7e308b9489f 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -50,6 +50,7 @@ rm tests/ui/c-variadic/copy.rs # same rm tests/ui/sanitizer/kcfi-c-variadic.rs # same rm tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs # variadics for calling conventions other than C unsupported rm tests/ui/delegation/fn-header.rs +rm tests/ui/c-variadic/roundtrip.rs # inline assembly features rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly @@ -144,6 +145,7 @@ rm tests/ui/consts/issue-33537.rs # same rm tests/ui/consts/const-mut-refs-crate.rs # same rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift rm -r tests/run-make/short-ice # ICE backtrace begin/end marker mismatch +rm -r tests/run-make/naked-dead-code-elimination # function not eliminated # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended From 10fba0bdce0d1b5b035a19959be9e433aa43e743 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Tue, 21 Apr 2026 13:12:36 +1000 Subject: [PATCH 28/45] Update to Cranelift 0.130 --- Cargo.lock | 76 +++++++++++++++++++++++----------------------- Cargo.toml | 26 ++++++++-------- src/pretty_clif.rs | 8 +---- 3 files changed, 52 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d84d2c57fc6b..979ae1be3c28b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,27 +43,27 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cranelift-assembler-x64" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f248321c6a7d4de5dcf2939368e96a397ad3f53b6a076e38d0104d1da326d37" +checksum = "6edb5bdd1af46714e3224a017fabbbd57f70df4e840eb5ad6a7429dc456119d6" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6d78ff1f7d9bf8b7e1afbedbf78ba49e38e9da479d4c8a2db094e22f64e2bc" +checksum = "a819599186e1b1a1f88d464e06045696afc7aa3e0cc018aa0b2999cb63d1d088" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6005ba640213a5b95382aeaf6b82bf028309581c8d7349778d66f27dc1180b" +checksum = "36e2c152d488e03c87b913bc2ed3414416eb1e0d66d61b49af60bf456a9665c7" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -71,18 +71,18 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fb5b134a12b559ff0c0f5af0fcd755ad380723b5016c4e0d36f74d39485340" +checksum = "b6559d4fbc253d1396e1f6beeae57fa88a244f02aaf0cde2a735afd3492d9b2e" dependencies = [ "wasmtime-internal-core", ] [[package]] name = "cranelift-codegen" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85837de8be7f17a4034a6b08816f05a3144345d2091937b39d415990daca28f4" +checksum = "96d9315d98d6e0a64454d4c83be2ee0e8055c3f80c3b2d7bcad7079f281a06ff" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e433faa87d38e5b8ff469e44a26fea4f93e58abd7a7c10bad9810056139700c9" +checksum = "d89c00a88081c55e3087c45bebc77e0cc973de2d7b44ef6a943c7122647b89f5" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -119,24 +119,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5397ba61976e13944ca71230775db13ee1cb62849701ed35b753f4761ed0a9b7" +checksum = "879f77c497a1eb6273482aa1ac3b23cb8563ff04edb39ed5dfcfd28c8deff8f5" [[package]] name = "cranelift-control" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc81c88765580720eb30f4fc2c1bfdb75fcbf3094f87b3cd69cecca79d77a245" +checksum = "498dc1f17a6910c88316d49c7176d8fa97cf10c30859c32a266040449317f963" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463feed5d46cf8763f3ba3045284cf706dd161496e20ec9c14afbb4ba09b9e66" +checksum = "c2acba797f6a46042ce82aaf7680d0c3567fe2001e238db9df649fd104a2727f" dependencies = [ "cranelift-bitset", "wasmtime-internal-core", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c5eca7696c1c04ab4c7ed8d18eadbb47d6cc9f14ec86fe0881bf1d7e97e261" +checksum = "4dca3df1d107d98d88f159ad1d5eaa2d5cdb678b3d5bcfadc6fc83d8ebb448ea" dependencies = [ "cranelift-codegen", "log", @@ -156,15 +156,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1153844610cc9c6da8cf10ce205e45da1a585b7688ed558aa808bbe2e4e6d77" +checksum = "f62dd18116d88bed649871feceda79dad7b59cc685ea8998c2b3e64d0e689602" [[package]] name = "cranelift-jit" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41836de8321b303d3d4188e58cc09c30c7645337342acfcfb363732695cae098" +checksum = "0a4942770ce6662b44d903493d7c5b00f9a986a713a61aae148306eaef21ebd4" dependencies = [ "anyhow", "cranelift-codegen", @@ -182,9 +182,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b731f66cb1b69b60a74216e632968ebdbb95c488d26aa1448ec226ae0ffec33e" +checksum = "fb5ca0d214ecee44405ea9f0c65a5318b41ac469e8258fd9fe944e564c1c1b0b" dependencies = [ "anyhow", "cranelift-codegen", @@ -193,9 +193,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97b583fe9a60f06b0464cee6be5a17f623fd91b217aaac99b51b339d19911af" +checksum = "f843b80360d7fdf61a6124642af7597f6d55724cf521210c34af8a1c66daca6e" dependencies = [ "cranelift-codegen", "libc", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9809d2d419cd18f17377f4ce64a7ad22eeda0d042c08833d3796657f1ddebc82" +checksum = "b9d212d15015c374333b11b833111b7c7e686bfaec02385af53611050bce7e9d" dependencies = [ "anyhow", "cranelift-codegen", @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.130.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8594dc6bb4860fa8292f1814c76459dbfb933e1978d8222de6380efce45c7cee" +checksum = "090ee5de58c6f17eb5e3a5ae8cf1695c7efea04ec4dd0ecba6a5b996c9bad7dc" [[package]] name = "crc32fast" @@ -338,9 +338,9 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "object" -version = "0.38.1" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" +checksum = "63944c133d03f44e75866bbd160b95af0ec3f6a13d936d69d31c81078cbc5baf" dependencies = [ "crc32fast", "hashbrown 0.16.1", @@ -482,9 +482,9 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "wasmtime-internal-core" -version = "43.0.0" +version = "44.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e671917bb6856ae360cb59d7aaf26f1cfd042c7b924319dd06fd380739fc0b2e" +checksum = "816a61a75275c6be435131fc625a4f5956daf24d9f9f59443e81cbef228929b3" dependencies = [ "hashbrown 0.16.1", "libm", @@ -492,9 +492,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "43.0.0" +version = "44.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3112806515fac8495883885eb8dbdde849988ae91fe6beb544c0d7c0f4c9aa" +checksum = "2fd683a94490bf755d016a09697b0955602c50106b1ded97d16983ab2ded9fed" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index 6707557f06f75..0564a8f4ba627 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,15 +8,15 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.130.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.130.0" } -cranelift-module = { version = "0.130.0" } -cranelift-native = { version = "0.130.0" } -cranelift-jit = { version = "0.130.0", optional = true } -cranelift-object = { version = "0.130.0" } +cranelift-codegen = { version = "0.131.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.131.0" } +cranelift-module = { version = "0.131.0" } +cranelift-native = { version = "0.131.0" } +cranelift-jit = { version = "0.131.0", optional = true } +cranelift-object = { version = "0.131.0" } target-lexicon = "0.13" gimli = { version = "0.33", default-features = false, features = ["write"] } -object = { version = "0.38.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.39.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.9.0", optional = true } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-43.0.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-44.0.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 65779b38ad1c0..918fe3d2a3895 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -60,7 +60,6 @@ use std::fmt; use std::io::Write; use cranelift_codegen::entity::SecondaryMap; -use cranelift_codegen::ir::Fact; use cranelift_codegen::ir::entities::AnyEntity; use cranelift_codegen::write::{FuncWriter, PlainWriter}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -182,13 +181,8 @@ impl FuncWriter for &'_ CommentWriter { _func: &Function, entity: AnyEntity, value: &dyn fmt::Display, - maybe_fact: Option<&Fact>, ) -> fmt::Result { - if let Some(fact) = maybe_fact { - write!(w, " {} ! {} = {}", entity, fact, value)?; - } else { - write!(w, " {} = {}", entity, value)?; - } + write!(w, " {} = {}", entity, value)?; if let Some(comment) = self.entity_comments.get(&entity) { writeln!(w, " ; {}", comment.replace('\n', "\n; ")) From 04564d165ffadb6f4a4136ab46ed5bdd8875a4f1 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Tue, 21 Apr 2026 13:18:10 +1000 Subject: [PATCH 29/45] Update to object 0.39.1 --- Cargo.lock | 21 +++++++++++++++------ Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 979ae1be3c28b..ca623eabaa2d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,6 +277,15 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +dependencies = [ + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -285,12 +294,12 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", ] [[package]] @@ -338,12 +347,12 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "object" -version = "0.39.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63944c133d03f44e75866bbd160b95af0ec3f6a13d936d69d31c81078cbc5baf" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" dependencies = [ "crc32fast", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "indexmap", "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 0564a8f4ba627..b775809a50e3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ cranelift-jit = { version = "0.131.0", optional = true } cranelift-object = { version = "0.131.0" } target-lexicon = "0.13" gimli = { version = "0.33", default-features = false, features = ["write"] } -object = { version = "0.39.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.39.1", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.9.0", optional = true } From a0871ed21b6be9cd1913ffad80f9e867f4547846 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Tue, 21 Apr 2026 18:45:55 +1000 Subject: [PATCH 30/45] Fix __eh_frame for AArch64 on macOS The relocations must use symbols (not sections), and the relative relocation needs ARM64_RELOC_SUBTRACTOR. The section must be in __TEXT rather than __DWARF, which is handled by using StandardSection::EhFrame. This also changes the section type for ELF x86-64. --- src/debuginfo/emit.rs | 2 +- src/debuginfo/object.rs | 54 +++++++++++++++++++++++------------------ src/debuginfo/unwind.rs | 12 ++++----- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index 8016c5a3005a2..cc1efef287517 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -43,7 +43,7 @@ impl DebugContext { let _: Result<()> = sections.for_each(|id, section| { if let Some(section_id) = section_map.get(&id) { for reloc in §ion.relocs { - product.add_debug_reloc(§ion_map, section_id, reloc); + product.add_debug_reloc(§ion_map, section_id, reloc, true); } } Ok(()) diff --git a/src/debuginfo/object.rs b/src/debuginfo/object.rs index 1c6e471cc870f..0af03ff33a43e 100644 --- a/src/debuginfo/object.rs +++ b/src/debuginfo/object.rs @@ -1,7 +1,7 @@ use cranelift_module::{DataId, FuncId}; use cranelift_object::ObjectProduct; use gimli::SectionId; -use object::write::{Relocation, StandardSegment}; +use object::write::{Relocation, StandardSection, StandardSegment}; use object::{RelocationEncoding, RelocationFlags, SectionKind}; use rustc_data_structures::fx::FxHashMap; @@ -16,6 +16,7 @@ pub(super) trait WriteDebugInfo { section_map: &FxHashMap, from: &Self::SectionId, reloc: &DebugReloc, + use_section_symbol: bool, ); } @@ -27,29 +28,31 @@ impl WriteDebugInfo for ObjectProduct { id: SectionId, data: Vec, ) -> (object::write::SectionId, object::write::SymbolId) { - let name = if self.object.format() == object::BinaryFormat::MachO { - id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info + let (section_id, align); + if id == SectionId::EhFrame { + section_id = self.object.section_id(StandardSection::EhFrame); + align = 8; } else { - id.name().to_string() - } - .into_bytes(); - - let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); - // FIXME use SHT_X86_64_UNWIND for .eh_frame - let section_id = self.object.add_section( - segment, - name, - if id == SectionId::DebugStr || id == SectionId::DebugLineStr { - SectionKind::DebugString - } else if id == SectionId::EhFrame { - SectionKind::ReadOnlyData + let name = if self.object.format() == object::BinaryFormat::MachO { + id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info } else { - SectionKind::Debug - }, - ); - self.object - .section_mut(section_id) - .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 }); + id.name().to_string() + } + .into_bytes(); + + let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); + section_id = self.object.add_section( + segment, + name, + if id == SectionId::DebugStr || id == SectionId::DebugLineStr { + SectionKind::DebugString + } else { + SectionKind::Debug + }, + ); + align = 1; + } + self.object.section_mut(section_id).set_data(data, align); let symbol_id = self.object.section_symbol(section_id); (section_id, symbol_id) } @@ -59,6 +62,7 @@ impl WriteDebugInfo for ObjectProduct { section_map: &FxHashMap, from: &Self::SectionId, reloc: &DebugReloc, + use_section_symbol: bool, ) { let (symbol, symbol_offset) = match reloc.name { DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0), @@ -69,7 +73,11 @@ impl WriteDebugInfo for ObjectProduct { } else { self.data_symbol(DataId::from_u32(id & !(1 << 31))) }; - self.object.symbol_section_and_offset(symbol_id).unwrap_or((symbol_id, 0)) + if use_section_symbol { + self.object.symbol_section_and_offset(symbol_id).unwrap_or((symbol_id, 0)) + } else { + (symbol_id, 0) + } } }; self.object diff --git a/src/debuginfo/unwind.rs b/src/debuginfo/unwind.rs index 33ffe4cc4e9c8..1ce424332db20 100644 --- a/src/debuginfo/unwind.rs +++ b/src/debuginfo/unwind.rs @@ -120,13 +120,12 @@ impl UnwindContext { func_id: FuncId, context: &Context, ) { - if let target_lexicon::OperatingSystem::MacOSX { .. } = - module.isa().triple().operating_system + let triple = module.isa().triple(); + if matches!(triple.operating_system, target_lexicon::OperatingSystem::MacOSX { .. }) + && triple.architecture == target_lexicon::Architecture::X86_64 { // The object crate doesn't currently support DW_GNU_EH_PE_absptr, which macOS - // requires for unwinding tables. In addition on arm64 it currently doesn't - // support 32bit relocations as we currently use for the unwinding table. - // See gimli-rs/object#415 and rust-lang/rustc_codegen_cranelift#1371 + // requires for unwinding tables. See gimli-rs/object#415. return; } @@ -250,8 +249,9 @@ impl UnwindContext { let mut section_map = FxHashMap::default(); section_map.insert(id, section_id); + let use_section_symbol = product.object.format() != object::BinaryFormat::MachO; for reloc in &eh_frame.0.relocs { - product.add_debug_reloc(§ion_map, §ion_id, reloc); + product.add_debug_reloc(§ion_map, §ion_id, reloc, use_section_symbol); } } } From e6e77ab00c360cda5e6c4323735a15d43c387cea Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:03:28 +0200 Subject: [PATCH 31/45] Temporarily allow releases when the bench job fails The bench job is broken because of a cargo regression. --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f9fd0cc7c5e0..a3ab9a91e3a8b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -242,7 +242,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 if: ${{ github.ref == 'refs/heads/main' }} - needs: [todo_check, rustfmt, test, bench, dist] + # FIXME add bench back once rust-lang/cargo#16925 has been fixed + needs: [todo_check, rustfmt, test, dist] permissions: contents: write # for creating the dev tag and release From 3c362ecfa67ff5252f0acfce045f93f1ec500637 Mon Sep 17 00:00:00 2001 From: Arjun Ramesh Date: Fri, 24 Apr 2026 12:19:55 -0400 Subject: [PATCH 32/45] Update documentation for `wasm32-wali-linux-musl` after integrating new LLVM 22 `wasm32-linux-muslwali` target changes --- .../src/platform-support/wasm32-wali-linux.md | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md index 001159b0d3266..f434c9e94867f 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md +++ b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md @@ -15,7 +15,7 @@ From the wider Wasm ecosystem perspective, implementing WALI within engines allo ## Requirements ### Compilation -This target is cross-compiled and requires an installation of the [WALI compiler/sysroot](https://github.com/arjunr2/WALI). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the "Execution" section below). +This target is cross-compiled and requires an installation of the [WALI sysroot](https://github.com/Wasm-Thin-Kernel-Interfaces/WALI.git). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the "Execution" section below). `wali` targets *minimally require* the following LLVM feature flags: @@ -31,7 +31,7 @@ This target is cross-compiled and requires an installation of the [WALI compiler > **Note**: Users can expect that new enabled-by-default Wasm features for LLVM are transitively incorporatable into this target -- see [wasm32-unknown-unknown](wasm32-unknown-unknown.md) for detailed information on WebAssembly features. -> **Note**: The WALI ABI is similar to default Clang wasm32 ABIs but *not identical*. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maintain minimum source code changes for 64-bit host platforms currently supported. This may change in the future as the spec evolves. +> **Note**: The WALI ABI is *not identical* to the default Clang wasm32 ABI. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maximize portability with minimum source code changes for currently supported 64-bit host platforms. These ABIs may converge in the future as the spec evolves. ### Execution Running generated WALI binaries also requires a supported compliant engine implementation -- a working implementation in the [WebAssembly Micro-Runtime (WAMR)](https://github.com/arjunr2/WALI) is included in the repo. @@ -41,38 +41,28 @@ Running generated WALI binaries also requires a supported compliant engine imple ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `config.toml` for the `musl` environment will look like this, where `` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI): +list in `bootstrap.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `bootstrap.toml` for the `musl` environment will look like this, where `` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI): ```toml [build] target = ["wasm32-wali-linux-musl"] [target.wasm32-wali-linux-musl] -musl-root = "/wali-musl/sysroot" -llvm-config = "/llvm-project/build/bin/llvm-config" -cc = "/llvm-project/build/bin/clang-18" -cxx = "/llvm-project/build/bin/clang-18" -ar = "/llvm-project/build/bin/llvm-ar" -ranlib = "/llvm-project/build/bin/llvm-ranlib" +musl-root = "/build/sysroot" +cc = "/build/llvm/bin/clang" +cxx = "/build/llvm/bin/clang++" +ar = "/build/llvm/bin/llvm-ar" +ranlib = "/build/llvm/bin/llvm-ranlib" llvm-libunwind = "system" crt-static = true ``` -> The `llvm-config` settings are only temporary, and the changes will eventually be upstreamed into LLVM - ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using -`build-std` or similar. - -Rust program builds can use this target normally. Currently, linking WALI programs may require pointing the `linker` to the llvm build in the [Cargo config](https://doc.rust-lang.org/cargo/reference/config.html) (until LLVM is upstreamed). A `config.toml` for Cargo will look like the following: - -```toml -[target.wasm32-wali-linux-musl] -linker = "/llvm-project/build/bin/lld" -``` +`build-std` or similar (with the appropriate sysroot links). Note that the following `cfg` directives are set for `wasm32-wali-linux-*`: From c20757fd30dee33aa6bc65cff83dfe920463f202 Mon Sep 17 00:00:00 2001 From: Arjun Ramesh Date: Fri, 24 Apr 2026 16:25:47 -0400 Subject: [PATCH 33/45] Add specific target diffs --- src/doc/rustc/src/platform-support/wasm32-wali-linux.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md index f434c9e94867f..c87cc1d5f863d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md +++ b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md @@ -31,7 +31,7 @@ This target is cross-compiled and requires an installation of the [WALI sysroot] > **Note**: Users can expect that new enabled-by-default Wasm features for LLVM are transitively incorporatable into this target -- see [wasm32-unknown-unknown](wasm32-unknown-unknown.md) for detailed information on WebAssembly features. -> **Note**: The WALI ABI is *not identical* to the default Clang wasm32 ABI. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maximize portability with minimum source code changes for currently supported 64-bit host platforms. These ABIs may converge in the future as the spec evolves. +> **Note**: The WALI ABI is *not identical* to the `wasm32-wasip2` or `wasm32-unknown-unknown` ABI. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to maximize portability with minimum source code changes for currently supported 64-bit host platforms. These ABIs may converge in the future as the spec evolves. ### Execution Running generated WALI binaries also requires a supported compliant engine implementation -- a working implementation in the [WebAssembly Micro-Runtime (WAMR)](https://github.com/arjunr2/WALI) is included in the repo. From da0fe8db677a4f0915b8f362a99978e93dc843ed Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 24 Apr 2026 13:11:16 +1000 Subject: [PATCH 34/45] Overhaul the code for running an incremental test revision The main goals of this overhaul are: - Introduce a dedicated `IncrRevKind` enum for exhaustive matching. - Eliminate any dependency on `PassMode` and `FailMode`. - Use a single code path for all incremental revision kinds. Separating incremental tests from the existing pass/fail enums should make it easier to overhaul the implementation of pass/fail expectations in UI tests. --- src/tools/compiletest/src/runtest.rs | 14 -- .../compiletest/src/runtest/incremental.rs | 166 ++++++++++-------- 2 files changed, 89 insertions(+), 91 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 568e307366641..ab268f944816f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -319,20 +319,6 @@ impl<'test> TestCx<'test> { TestMode::RustdocJs => true, TestMode::Ui => pm.is_some() || self.props.fail_mode > Some(FailMode::Build), TestMode::Crashes => false, - TestMode::Incremental => { - let revision = - self.revision.expect("incremental tests require a list of revisions"); - if revision.starts_with("cpass") - || revision.starts_with("bpass") - || revision.starts_with("rpass") - { - true - } else if revision.starts_with("bfail") { - false - } else { - panic!("revision name must begin with `cpass`, `bfail`, `bpass`, or `rpass`"); - } - } mode => panic!("unimplemented for mode {:?}", mode), } } diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 85e0c89a8d018..6529882715a90 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -1,26 +1,43 @@ -use super::{Emit, FailMode, PassMode, ProcRes, TestCx, WillExecute}; +use std::sync::LazyLock; + +use crate::runtest::{Emit, TestCx, WillExecute}; +use crate::util::string_enum; + +string_enum!( + /// How far an incremental test revision should proceed through the compile/run + /// sequence, and whether the last step should succeed or fail, as determined + /// from the start of the revision name. + #[derive(Clone, Copy, PartialEq, Eq)] + enum IncrRevKind { + CheckPass => "cpass", + BuildFail => "bfail", + BuildPass => "bpass", + RunPass => "rpass", + } +); + +impl IncrRevKind { + fn for_revision_name(rev_name: &str) -> Result { + static MESSAGE: LazyLock = LazyLock::new(|| { + let values = IncrRevKind::STR_VARIANTS + .iter() + .map(|s| format!("`{s}`")) + .collect::>() + .join(", "); + format!("incremental revision name must begin with one of: {values}") + }); + + IncrRevKind::VARIANTS + .iter() + .copied() + .find(|kind| rev_name.starts_with(kind.to_str())) + .ok_or_else(|| MESSAGE.as_str()) + } +} impl TestCx<'_> { + /// Runs a single revision of an incremental test. pub(super) fn run_incremental_test(&self) { - // Basic plan for a test incremental/foo/bar.rs: - // - load list of revisions rpass1, bfail2, rpass3 - // - each should begin with `bfail`, `bpass`, or `rpass` - // - if `bfail`, expect compilation to fail - // - if `bpass`, expect compilation to succeed, don't execute - // - if `rpass`, expect compilation and execution to succeed - // - create a directory build/foo/bar.incremental - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1 - // - because name of revision starts with "rpass", expect success - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C bfail2 - // - because name of revision starts with "bfail", expect an error - // - load expected errors as usual, but filter for those with `[bfail2]` - // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3 - // - because name of revision starts with "rpass", expect success - // - execute build/foo/bar.exe and save output - // - // FIXME -- use non-incremental mode as an oracle? That doesn't apply - // to #[rustc_clean] tests I guess - let revision = self.revision.expect("incremental tests require a list of revisions"); // Incremental workproduct directory should have already been created. @@ -31,68 +48,63 @@ impl TestCx<'_> { write!(self.stdout, "revision={:?} props={:#?}", revision, self.props); } - if revision.starts_with("cpass") { - self.run_cpass_test(); - } else if revision.starts_with("bpass") { - self.run_bpass_test(); - } else if revision.starts_with("rpass") { - self.run_rpass_test(); - } else if revision.starts_with("bfail") { - self.run_bfail_test(); - } else { - self.fatal("revision name must begin with `bfail`, `bpass`, or `rpass`"); + // Determine the revision kind from the revision name. + // The revision kind should be matched exhaustively to ensure that no cases are missed. + let rev_kind = IncrRevKind::for_revision_name(revision).unwrap_or_else(|e| self.fatal(e)); + + // Compile the test for this revision. + let emit = match rev_kind { + IncrRevKind::CheckPass => Emit::Metadata, // Do a check build. + IncrRevKind::BuildFail | IncrRevKind::BuildPass | IncrRevKind::RunPass => Emit::None, + }; + let will_execute = match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildFail | IncrRevKind::BuildPass => { + WillExecute::No + } + IncrRevKind::RunPass => { + // Yes, unless running test binaries is disabled. + self.run_if_enabled() + } + }; + let proc_res = &self.compile_test(will_execute, emit); + + // Check the compiler's exit status. + match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildPass | IncrRevKind::RunPass => { + // Compilation should have succeeded. + if !proc_res.status.success() { + self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res); + } + } + + IncrRevKind::BuildFail => { + // Compilation should have failed, with the expected status code. + if proc_res.status.success() { + self.fatal_proc_rec("incremental test did not emit an error", proc_res); + } + if !self.props.dont_check_failure_status { + self.check_correct_failure_status(proc_res); + } + } } - } - - fn run_cpass_test(&self) { - let proc_res = self.compile_test(WillExecute::No, Emit::Metadata); - self.check_if_test_should_compile(None, Some(PassMode::Check), &proc_res); - self.check_compiler_output_for_incr(&proc_res); - } - - fn run_bpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let proc_res = self.compile_test(WillExecute::No, emit_metadata); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - self.check_compiler_output_for_incr(&proc_res); - } - - fn run_rpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let should_run = self.run_if_enabled(); - let proc_res = self.compile_test(should_run, emit_metadata); - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - self.check_compiler_output_for_incr(&proc_res); - - if let WillExecute::Disabled = should_run { - return; - } - - let proc_res = self.exec_compiled_test(); - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - } - - fn run_bfail_test(&self) { - let pm = self.pass_mode(); - let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); - self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res); - self.check_compiler_output_for_incr(&proc_res); - } - - fn check_compiler_output_for_incr(&self, proc_res: &ProcRes) { + // Check compilation output. let output_to_check = self.get_output(proc_res); self.check_expected_errors(&proc_res); self.check_all_error_patterns(&output_to_check, proc_res); self.check_forbid_output(&output_to_check, proc_res); + + // Run the binary and check its exit status, if appropriate. + match rev_kind { + IncrRevKind::CheckPass | IncrRevKind::BuildFail | IncrRevKind::BuildPass => {} + IncrRevKind::RunPass => { + if self.config.run_enabled() { + let run_proc_res = self.exec_compiled_test(); + if !run_proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &run_proc_res); + } + } + } + } } } From 569ad9986443503f23c534d6c4d9f34e823f5c69 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 25 Apr 2026 23:17:37 -0700 Subject: [PATCH 35/45] Only exclude the 155473 change for 1-byte bool-likes That's the thing we handle differently in codegen (see `to_immediate_scalar`) so if the other ones are fine, that helps narrow it down further. --- compiler/rustc_abi/src/lib.rs | 3 ++- tests/codegen-llvm/function-arguments.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b9414df2b86d7..22300fda5f698 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2084,7 +2084,8 @@ impl Niche { let distance_end_zero = max_value - v.end; // FIXME: this ought to work for `bool` too, but that seems to be hitting a miscompilation // - if count == 1 && v != (WrappingRange { start: 0, end: 1 }) { + let is_bool = size.bytes() == 1 && v == WrappingRange { start: 0, end: 1 }; + if count == 1 && !is_bool { // We only need one, so just pick the one closest to zero. // Not only does that obviously use zero if it's possible, but it also // simplifies testing things like `Option`, since looking for `-1` diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index 80e6ac7bb0f03..87be219a2b2e0 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -297,7 +297,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } -// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 0, 3\))?}} %x.0, i16 %x.1) +// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 -1, 2\))?}} %x.0, i16 %x.1) #[no_mangle] pub fn enum_id_1(x: Option>) -> Option> { x From b7996bdc9a4e702c9e3b451f681bc9aa81a8bceb Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 24 Feb 2026 13:28:23 +0000 Subject: [PATCH 36/45] Existing code nits --- .../rustc_borrowck/src/handle_placeholders.rs | 18 +++++------ .../rustc_borrowck/src/region_infer/mod.rs | 31 +++++++++++-------- .../src/graph/scc/mod.rs | 2 +- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 2a7dc8ba10162..11b8890346dfb 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -35,18 +35,18 @@ pub(crate) struct LoweredConstraints<'tcx> { pub(crate) placeholder_indices: PlaceholderIndices<'tcx>, } -impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { - pub(crate) fn init(definitions: &'d IndexVec>) -> Self { - Self { scc_to_annotation: IndexVec::new(), definitions } - } -} - /// A Visitor for SCC annotation construction. pub(crate) struct SccAnnotations<'d, 'tcx, A: scc::Annotation> { pub(crate) scc_to_annotation: IndexVec, definitions: &'d IndexVec>, } +impl<'d, 'tcx, A: scc::Annotation> SccAnnotations<'d, 'tcx, A> { + pub(crate) fn init(definitions: &'d IndexVec>) -> Self { + Self { scc_to_annotation: IndexVec::new(), definitions } + } +} + impl scc::Annotations for SccAnnotations<'_, '_, RegionTracker> { fn new(&self, element: RegionVid) -> RegionTracker { RegionTracker::new(element, &self.definitions[element]) @@ -118,7 +118,7 @@ impl RegionTracker { } /// The largest universe this SCC can name. It's the smallest - /// largest nameable universe of any reachable region, or + /// max-nameable-universe of any reachable region, or /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)` pub(crate) fn max_nameable_universe(self) -> UniverseIndex { self.max_nameable_universe.0 @@ -208,7 +208,7 @@ pub(super) fn region_definitions<'tcx>( /// graph such that there is a series of constraints /// A: B: C: ... : X where /// A contains a placeholder whose universe cannot be named by X, -/// add a constraint that A: 'static. This is a safe upper bound +/// add a constraint that X: 'static. This is a safe upper bound /// in the face of borrow checker/trait solver limitations that will /// eventually go away. /// @@ -327,8 +327,6 @@ pub(crate) fn rewrite_placeholder_outlives<'tcx>( for scc in sccs.all_sccs() { // No point in adding 'static: 'static! - // This micro-optimisation makes somewhat sense - // because static outlives *everything*. if scc == sccs.scc(fr_static) { continue; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5cdda777723b3..2a759387788a7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -501,43 +501,48 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut errors_buffer = RegionErrors::new(infcx.tcx); - // If this is a closure, we can propagate unsatisfied - // `outlives_requirements` to our creator, so create a vector - // to store those. Otherwise, we'll pass in `None` to the - // functions below, which will trigger them to report errors - // eagerly. - let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); + // If this is a nested body, we propagate unsatisfied + // outlives constraints to the parent body instead of + // eagerly erroing. + let mut propagated_outlives_requirements = + infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); debug!(?errors_buffer); - debug!(?outlives_requirements); + debug!(?propagated_outlives_requirements); // In Polonius mode, the errors about missing universal region relations are in the output // and need to be emitted or propagated. Otherwise, we need to check whether the // constraints were too strong, and if so, emit or propagate those errors. if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { self.check_polonius_subset_errors( - outlives_requirements.as_mut(), + propagated_outlives_requirements.as_mut(), &mut errors_buffer, polonius_output .as_ref() .expect("Polonius output is unavailable despite `-Z polonius`"), ); } else { - self.check_universal_regions(outlives_requirements.as_mut(), &mut errors_buffer); + self.check_universal_regions( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); } debug!(?errors_buffer); - let outlives_requirements = outlives_requirements.unwrap_or_default(); + let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); - if outlives_requirements.is_empty() { + if propagated_outlives_requirements.is_empty() { (None, errors_buffer) } else { let num_external_vids = self.universal_regions().num_global_and_external_regions(); ( - Some(ClosureRegionRequirements { num_external_vids, outlives_requirements }), + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements: propagated_outlives_requirements, + }), errors_buffer, ) } diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 10abfd7a55ced..c04688e0a49fa 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -27,7 +27,7 @@ mod tests; /// the max/min element of the SCC, or all of the above. /// /// Concretely, the both merge operations must commute, e.g. where `merge` -/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)` +/// is `update_scc` and `update_reachable`: `a.merge(b) == b.merge(a)` /// /// In general, what you want is probably always min/max according /// to some ordering, potentially with side constraints (min x such From f5c39ef72a46c01c144736f6ab8758966766f884 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 28 Apr 2026 02:46:10 +0000 Subject: [PATCH 37/45] Fix passing paths with space into dlltool --- compiler/rustc_codegen_ssa/src/back/archive.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 3f12e857391b2..9b9fa737d6d8d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -217,12 +217,10 @@ fn create_mingw_dll_import_lib( // able to control the *exact* spelling of each of the symbols that are being imported: // hence we don't want `dlltool` adding leading underscores automatically. let dlltool = find_binutils_dlltool(sess); - let temp_prefix = { - let mut path = PathBuf::from(&output_path); - path.pop(); - path.push(lib_name); - path - }; + // temp_prefix doesn't handle paths with spaces so + // use a relative path and set the current working directory + let cwd = output_path.parent().unwrap_or(output_path); + let temp_prefix = lib_name; // dlltool target architecture args from: // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69 let (dlltool_target_arch, dlltool_target_bitness) = match &sess.target.arch { @@ -246,7 +244,8 @@ fn create_mingw_dll_import_lib( .arg(dlltool_target_bitness) .arg("--no-leading-underscore") .arg("--temp-prefix") - .arg(temp_prefix); + .arg(temp_prefix) + .current_dir(cwd); match dlltool_cmd.output() { Err(e) => { From 2a8e588c9049da90b0aeb2d43b89e4186532ef22 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Thu, 23 Apr 2026 15:42:44 +0200 Subject: [PATCH 38/45] Add `--print=backend-has-mnemonic` and `needs-asm-mnemonic` directive Add infrastructure to query LLVM backend for specific assembly mnemonics and use it in compiletest to conditionally run tests based on instruction availability. This fixes test failures with naked-dead-code-elimination which requires the `RET` mnemonic. Co-authored-by: Folkert de Vries --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_codegen_llvm/src/llvm_util.rs | 11 ++++ compiler/rustc_driver_impl/src/lib.rs | 3 + .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 20 +++++++ .../rustc_session/src/config/print_request.rs | 37 ++++++++++-- .../rustc-dev-guide/src/tests/compiletest.md | 11 ++++ .../rustc-dev-guide/src/tests/directives.md | 3 + .../src/directives/directive_names.rs | 1 + src/tools/compiletest/src/directives/needs.rs | 60 +++++++++++++++++++ src/tools/compiletest/src/directives/tests.rs | 22 +++++++ .../naked-dead-code-elimination/rmake.rs | 1 + .../help-diff.diff | 2 +- .../unstable-invalid-print-request-help.err | 2 +- tests/run-make/rustc-help/help-v.stdout | 2 +- tests/run-make/rustc-help/help.stdout | 2 +- .../invalid/print-without-arg.stderr | 2 +- tests/ui/compile-flags/invalid/print.stderr | 2 +- .../ui/print-request/print-lints-help.stderr | 2 +- 18 files changed, 171 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 525d1dbe9d0d3..bed9242a3dbcf 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2343,6 +2343,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; + pub(crate) fn LLVMRustTargetHasMnemonic(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); pub(crate) fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 180559d28d848..e9983d11c127f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -480,6 +480,10 @@ pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) { match req.kind { PrintKind::TargetCPUs => print_target_cpus(sess, tm.raw(), out), PrintKind::TargetFeatures => print_target_features(sess, tm.raw(), out), + PrintKind::BackendHasMnemonic => { + let mnemonic = req.arg.as_deref().expect("BackendHasMnemonic requires arg"); + print_target_has_mnemonic(tm.raw(), mnemonic, out) + } _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req), } } @@ -738,3 +742,10 @@ pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } + +fn print_target_has_mnemonic(tm: &llvm::TargetMachine, mnemonic: &str, out: &mut String) { + use std::fmt::Write; + let cstr = SmallCStr::new(mnemonic); + let has_mnemonic = unsafe { llvm::LLVMRustTargetHasMnemonic(tm, cstr.as_ptr()) }; + writeln!(out, "{}", has_mnemonic).unwrap(); +} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c15c3c229398c..b05f5bc4a8e20 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -804,6 +804,9 @@ fn print_crate_info( let calling_conventions = rustc_abi::all_names(); println_info!("{}", calling_conventions.join("\n")); } + BackendHasMnemonic => { + codegen_backend.print(req, &mut crate_info, sess); + } BackendHasZstd => { let has_zstd: bool = codegen_backend.has_zstd(); println_info!("{has_zstd}"); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index b4f6bb4583c10..bad99f34567d9 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/LTO/LTO.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" @@ -94,6 +95,25 @@ extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, return MCInfo->checkFeatures(std::string("+") + Feature); } +/// Check whether the target has a specific assembly mnemonic like `ret` or +/// `nop`. +/// This should be fast enough but if its not we have to look into another +/// method of checking. +extern "C" bool LLVMRustTargetHasMnemonic(LLVMTargetMachineRef TM, + const char *Mnemonic) { + TargetMachine *Target = unwrap(TM); + const MCInstrInfo *MII = Target->getMCInstrInfo(); + StringRef MnemonicRef(Mnemonic); + + for (unsigned i = 0; i < MII->getNumOpcodes(); i++) { + StringRef Name = MII->getName(i); + if (Name.equals_insensitive(MnemonicRef)) { + return true; + } + } + return false; +} + enum class LLVMRustCodeModel { Tiny, Small, diff --git a/compiler/rustc_session/src/config/print_request.rs b/compiler/rustc_session/src/config/print_request.rs index dc53fcc6955f7..7c8ca4c0d3df3 100644 --- a/compiler/rustc_session/src/config/print_request.rs +++ b/compiler/rustc_session/src/config/print_request.rs @@ -15,6 +15,7 @@ use crate::macros::AllVariants; pub struct PrintRequest { pub kind: PrintKind, pub out: OutFileName, + pub arg: Option, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -22,6 +23,7 @@ pub struct PrintRequest { pub enum PrintKind { // tidy-alphabetical-start AllTargetSpecsJson, + BackendHasMnemonic, BackendHasZstd, CallingConventions, Cfg, @@ -60,6 +62,7 @@ impl PrintKind { match self { // tidy-alphabetical-start AllTargetSpecsJson => "all-target-specs-json", + BackendHasMnemonic => "backend-has-mnemonic", BackendHasZstd => "backend-has-zstd", CallingConventions => "calling-conventions", Cfg => "cfg", @@ -113,7 +116,8 @@ impl PrintKind { // Unstable values: AllTargetSpecsJson => false, - BackendHasZstd => false, // (perma-unstable, for use by compiletest) + BackendHasMnemonic => false, // (perma-unstable, for use by compiletest) + BackendHasZstd => false, // (perma-unstable, for use by compiletest) CheckCfg => false, CrateRootLintLevels => false, SupportedCrateTypes => false, @@ -150,11 +154,19 @@ pub(crate) fn collect_print_requests( ) -> Vec { let mut prints = Vec::::new(); if cg.target_cpu.as_deref() == Some("help") { - prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout }); + prints.push(PrintRequest { + kind: PrintKind::TargetCPUs, + out: OutFileName::Stdout, + arg: None, + }); cg.target_cpu = None; }; if cg.target_feature == "help" { - prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout }); + prints.push(PrintRequest { + kind: PrintKind::TargetFeatures, + out: OutFileName::Stdout, + arg: None, + }); cg.target_feature = String::new(); } @@ -167,9 +179,22 @@ pub(crate) fn collect_print_requests( prints.extend(matches.opt_strs("print").into_iter().map(|req| { let (req, out) = split_out_file_name(&req); - let kind = if let Some(print_kind) = PrintKind::from_str(req) { + let (kind, arg) = if let Some(mnemonic) = req.strip_prefix("backend-has-mnemonic") { + check_print_request_stability(early_dcx, unstable_opts, PrintKind::BackendHasMnemonic); + // BackendHasMnemonic requires a mnemonic argument + if let Some(mnemonic) = mnemonic.strip_prefix(':') + && !mnemonic.is_empty() + { + (PrintKind::BackendHasMnemonic, Some(mnemonic.to_string())) + } else { + early_dcx.early_fatal( + "expected mnemonic name after `--print=backend-has-mnemonic:`, \ + for example: `--print=backend-has-mnemonic:RET`", + ); + } + } else if let Some(print_kind) = PrintKind::from_str(req) { check_print_request_stability(early_dcx, unstable_opts, print_kind); - print_kind + (print_kind, None) } else { let is_nightly = nightly_options::match_is_nightly_build(matches); emit_unknown_print_request_help(early_dcx, req, is_nightly) @@ -185,7 +210,7 @@ pub(crate) fn collect_print_requests( } } - PrintRequest { kind, out } + PrintRequest { kind, out, arg } })); prints diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 4c534e9ae0eda..53a6c0cb5737d 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -346,6 +346,17 @@ See also the [codegen tests](#codegen-tests) for a similar set of tests. If you need to work with `#![no_std]` cross-compiling tests, consult the [`minicore` test auxiliary](./minicore.md) chapter. +#### Conditional assembly tests based on instruction support + +Tests that depend on specific assembly instructions being available can use the +`//@ needs-asm-mnemonic: ` directive. This will skip the test if the +target backend does not support the specified instruction mnemonic. + +For example, a test that requires the `RET` instruction: +```rust,ignore +//@ needs-asm-mnemonic: RET +``` + [`tests/assembly-llvm`]: https://github.com/rust-lang/rust/tree/HEAD/tests/assembly-llvm diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 76bf2cdbea667..9498f7953ad04 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -163,6 +163,9 @@ The following directives will check rustc build settings and target settings: For tests that cross-compile to explicit targets via `--target`, use `needs-llvm-components` instead to ensure the appropriate backend is available. +- `needs-asm-mnemonic: ` — ignores if the target backend does not + support the specified assembly mnemonic (e.g., `RET`, `NOP`). + Only supported with the LLVM backend. - `needs-profiler-runtime` — ignores the test if the profiler runtime was not enabled for the target (`build.profiler = true` in `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 34c6c1374b632..949c5ebfb29a7 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -156,6 +156,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "minicore-compile-flags", + "needs-asm-mnemonic", "needs-asm-support", "needs-backends", "needs-crate-type", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index e9f3d6c28d6ef..88ca347edd0a5 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -290,6 +290,37 @@ pub(super) fn handle_needs( } } + if name == "needs-asm-mnemonic" { + let Some(rest) = ln.value_after_colon() else { + return IgnoreDecision::Error { + message: "expected `needs-asm-mnemonic` to have a mnemonic name after colon" + .to_string(), + }; + }; + + if !config.default_codegen_backend.is_llvm() { + return IgnoreDecision::Ignore { + reason: "skipping test as non-LLVM backend does not support mnemonic queries" + .to_string(), + }; + } + + let mnemonic = rest.trim(); + let has_mnemonic = match mnemonic { + "ret" => cache.has_ret_mnemonic, + "nop" => cache.has_nop_mnemonic, + _ => has_mnemonic(config, mnemonic), + }; + + if has_mnemonic { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!("skipping test as target does not have `{mnemonic}` mnemonic"), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } @@ -352,6 +383,10 @@ pub(super) struct CachedNeedsConditions { symlinks: bool, /// Whether LLVM built with zstd, for the `needs-llvm-zstd` directive. llvm_zstd: bool, + /// Might add particular other mnemonics heavily needed by tests here. + /// Otherwise call into llvm for every check + has_ret_mnemonic: bool, + has_nop_mnemonic: bool, } impl CachedNeedsConditions { @@ -399,6 +434,8 @@ impl CachedNeedsConditions { llvm_zstd: llvm_has_zstd(&config), dlltool: find_dlltool(&config), symlinks: has_symlinks(), + has_ret_mnemonic: has_mnemonic(config, "ret"), + has_nop_mnemonic: has_mnemonic(config, "nop"), } } } @@ -466,3 +503,26 @@ fn llvm_has_zstd(config: &Config) -> bool { _ => panic!("unexpected output from `--print=backend-has-zstd`: {output:?}"), } } + +fn has_mnemonic(config: &Config, mnemonic: &str) -> bool { + if !config.default_codegen_backend.is_llvm() { + return false; + } + + let target_flag = format!("--target={}", config.target); + let output = query_rustc_output( + config, + &[ + &target_flag, + "-Zunstable-options", + &format!("--print=backend-has-mnemonic:{}", mnemonic), + ], + Default::default(), + ); + + match output.trim() { + "true" => true, + "false" => false, + _ => panic!("unexpected output from `--print=backend-has-mnemonic:{mnemonic}`: {output:?}"), + } +} diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 4cd75fcfa511a..56d52982a8211 100644 --- a/src/tools/compiletest/src/directives/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs @@ -1254,3 +1254,25 @@ fn test_edition_range_edition_to_test() { assert_edition_to_test(2018, range, Some(e2024)); assert_edition_to_test(2018, range, Some(efuture)); } + +#[test] +fn needs_asm_mnemonic() { + let config_x86_64 = cfg().target("x86_64-unknown-linux-gnu").build(); + let config_aarch64 = cfg().target("aarch64-unknown-linux-gnu").build(); + + // invalid mnemonic + assert!(check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:GRUGGY")); + assert!(check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:gruggy")); + + // valid x86 and aarch64 + assert!(!check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:RET")); + assert!(!check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:ret")); + + // this is aarch64 specific + assert!(check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:ldrsbwui")); + assert!(!check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:LDRSBWui")); + + // this is x86 specific + assert!(check_ignore(&config_aarch64, "//@ needs-asm-mnemonic:CMPxCHG16B")); + assert!(!check_ignore(&config_x86_64, "//@ needs-asm-mnemonic:CMPXchg16B")); +} diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs index 1be22de367c99..8e4c26fc34508 100644 --- a/tests/run-make/naked-dead-code-elimination/rmake.rs +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -1,5 +1,6 @@ //@ ignore-cross-compile //@ needs-asm-support +//@ needs-asm-mnemonic: RET use run_make_support::symbols::object_contains_any_symbol; use run_make_support::{bin_name, rustc}; diff --git a/tests/run-make/print-request-help-stable-unstable/help-diff.diff b/tests/run-make/print-request-help-stable-unstable/help-diff.diff index e382a24782711..828a98d96b563 100644 --- a/tests/run-make/print-request-help-stable-unstable/help-diff.diff +++ b/tests/run-make/print-request-help-stable-unstable/help-diff.diff @@ -2,6 +2,6 @@ error: unknown print request: `xxx` | - = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models` -+ = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` ++ = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err index 70764ea13aa87..d0e4c81f1de9d 100644 --- a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err +++ b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err @@ -1,5 +1,5 @@ error: unknown print request: `xxx` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index 0acbb766c1556..1531f61089e9a 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -43,7 +43,7 @@ Options: --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o Write output to FILENAME diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index 4075dd0282999..f96feccf35980 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -43,7 +43,7 @@ Options: --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o Write output to FILENAME diff --git a/tests/ui/compile-flags/invalid/print-without-arg.stderr b/tests/ui/compile-flags/invalid/print-without-arg.stderr index ff9669614360a..98788b4b87228 100644 --- a/tests/ui/compile-flags/invalid/print-without-arg.stderr +++ b/tests/ui/compile-flags/invalid/print-without-arg.stderr @@ -3,5 +3,5 @@ error: Argument to option 'print' missing --print [=] Compiler information to print on stdout (or to a file) INFO may be one of - . + . diff --git a/tests/ui/compile-flags/invalid/print.stderr b/tests/ui/compile-flags/invalid/print.stderr index e2521ebf26a41..3eb7634d915db 100644 --- a/tests/ui/compile-flags/invalid/print.stderr +++ b/tests/ui/compile-flags/invalid/print.stderr @@ -1,5 +1,5 @@ error: unknown print request: `yyyy` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/print-request/print-lints-help.stderr b/tests/ui/print-request/print-lints-help.stderr index d39c6326e318b..c6e74e7dce7b6 100644 --- a/tests/ui/print-request/print-lints-help.stderr +++ b/tests/ui/print-request/print-lints-help.stderr @@ -1,6 +1,6 @@ error: unknown print request: `lints` | - = help: valid print requests are: `all-target-specs-json`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `backend-has-mnemonic`, `backend-has-zstd`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `target-spec-json-schema`, `tls-models` = help: use `-Whelp` to print a list of lints = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information From 4d4058bfb43776e97bc71165b0e01fb008af6d6f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 Apr 2026 10:24:58 +0200 Subject: [PATCH 39/45] Add regression test for hkl const closures --- .../consts/const-closure-hkl.current.stderr | 17 +++++++++++++++ tests/ui/consts/const-closure-hkl.rs | 21 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/ui/consts/const-closure-hkl.current.stderr create mode 100644 tests/ui/consts/const-closure-hkl.rs diff --git a/tests/ui/consts/const-closure-hkl.current.stderr b/tests/ui/consts/const-closure-hkl.current.stderr new file mode 100644 index 0000000000000..ac6b77901ae44 --- /dev/null +++ b/tests/ui/consts/const-closure-hkl.current.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `for<'a> {closure@$DIR/const-closure-hkl.rs:11:21: 11:48}: [const] FnOnce(&'a usize, &'a usize)` is not satisfied + --> $DIR/const-closure-hkl.rs:13:19 + | +LL | chaining_impl(len_chain); + | ------------- ^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `chaining_impl` + --> $DIR/const-closure-hkl.rs:17:32 + | +LL | const fn chaining_impl(x: impl for<'a> [const] FnOnce(&'a usize, &'a usize)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `chaining_impl` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-closure-hkl.rs b/tests/ui/consts/const-closure-hkl.rs new file mode 100644 index 0000000000000..62282ab91e832 --- /dev/null +++ b/tests/ui/consts/const-closure-hkl.rs @@ -0,0 +1,21 @@ +//! Regression test for hkl const closures not working in old solver + +//@[next] check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(const_trait_impl)] +#![feature(const_closures)] +const fn partial_compare() { + let len_chain = const move |_a: &_, _b: &_| {}; + + chaining_impl(len_chain); + //[current]~^ ERROR: [const] FnOnce(&'a usize, &'a usize)` is not satisfied +} + +const fn chaining_impl(x: impl for<'a> [const] FnOnce(&'a usize, &'a usize)) { + std::mem::forget(x); +} + +fn main() {} From b465c5642b4e0de570dfa24e2d40a347888a3a57 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 Apr 2026 10:31:16 +0200 Subject: [PATCH 40/45] Handle hkl const closures --- .../rustc_trait_selection/src/traits/effects.rs | 6 +----- .../ui/consts/const-closure-hkl.current.stderr | 17 ----------------- tests/ui/consts/const-closure-hkl.rs | 3 +-- 3 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 tests/ui/consts/const-closure-hkl.current.stderr diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index f0587b8e4e23e..0f36edcdd830e 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -554,11 +554,7 @@ fn evaluate_host_effect_for_fn_goal<'tcx>( // but they don't really need to right now. ty::CoroutineClosure(_, _) => return Err(EvaluationFailure::NoSolution), - ty::Closure(def, args) => { - // For now we limit ourselves to closures without binders. The next solver can handle them. - args.as_closure().sig().no_bound_vars().ok_or(EvaluationFailure::NoSolution)?; - (def, args) - } + ty::Closure(def, args) => (def, args), // Everything else needs explicit impls or cannot have an impl _ => return Err(EvaluationFailure::NoSolution), diff --git a/tests/ui/consts/const-closure-hkl.current.stderr b/tests/ui/consts/const-closure-hkl.current.stderr deleted file mode 100644 index ac6b77901ae44..0000000000000 --- a/tests/ui/consts/const-closure-hkl.current.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0277]: the trait bound `for<'a> {closure@$DIR/const-closure-hkl.rs:11:21: 11:48}: [const] FnOnce(&'a usize, &'a usize)` is not satisfied - --> $DIR/const-closure-hkl.rs:13:19 - | -LL | chaining_impl(len_chain); - | ------------- ^^^^^^^^^ - | | - | required by a bound introduced by this call - | -note: required by a bound in `chaining_impl` - --> $DIR/const-closure-hkl.rs:17:32 - | -LL | const fn chaining_impl(x: impl for<'a> [const] FnOnce(&'a usize, &'a usize)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `chaining_impl` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-closure-hkl.rs b/tests/ui/consts/const-closure-hkl.rs index 62282ab91e832..25927b3a61ecd 100644 --- a/tests/ui/consts/const-closure-hkl.rs +++ b/tests/ui/consts/const-closure-hkl.rs @@ -1,6 +1,6 @@ //! Regression test for hkl const closures not working in old solver -//@[next] check-pass +//@ check-pass //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver @@ -11,7 +11,6 @@ const fn partial_compare() { let len_chain = const move |_a: &_, _b: &_| {}; chaining_impl(len_chain); - //[current]~^ ERROR: [const] FnOnce(&'a usize, &'a usize)` is not satisfied } const fn chaining_impl(x: impl for<'a> [const] FnOnce(&'a usize, &'a usize)) { From 3b6080cb20924f0c4f94e47bbbbfcae8b07d82e5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:58:20 +0200 Subject: [PATCH 41/45] Rustup to rustc 1.97.0-nightly (52b6e2c20 2026-04-27) --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 42db240bc4f86..486078185db84 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-04-20" +channel = "nightly-2026-04-28" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From f0b095068a8d38f5b76888189a16a247a19bb03a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 28 Apr 2026 09:35:44 +0000 Subject: [PATCH 42/45] Test that raw-dylib works with whitespace paths --- tests/run-make/raw-dylib-whitespace/main.rs | 18 ++++++++++++++++++ tests/run-make/raw-dylib-whitespace/rmake.rs | 15 +++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/run-make/raw-dylib-whitespace/main.rs create mode 100644 tests/run-make/raw-dylib-whitespace/rmake.rs diff --git a/tests/run-make/raw-dylib-whitespace/main.rs b/tests/run-make/raw-dylib-whitespace/main.rs new file mode 100644 index 0000000000000..023c3570c3262 --- /dev/null +++ b/tests/run-make/raw-dylib-whitespace/main.rs @@ -0,0 +1,18 @@ +type BOOL = i32; + +#[cfg_attr( + target_arch = "x86", + link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") +)] +#[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] +extern "system" { + fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} + +fn main() { + let mut num: u8 = 0; + unsafe { + ProcessPrng(&mut num, 1); + } + println!("{num}"); +} diff --git a/tests/run-make/raw-dylib-whitespace/rmake.rs b/tests/run-make/raw-dylib-whitespace/rmake.rs new file mode 100644 index 0000000000000..45a557aa37387 --- /dev/null +++ b/tests/run-make/raw-dylib-whitespace/rmake.rs @@ -0,0 +1,15 @@ +// Ensure that raw-dylib still works if the output directory contains spaces. + +//@ only-windows-gnu +//@ ignore-cross-compile + +use run_make_support::{rfs, rustc}; + +fn main() { + let out_dir = "path with spaces"; + rfs::create_dir_all(out_dir); + unsafe { + std::env::set_var("TMP", out_dir); + } + rustc().crate_type("bin").input("main.rs").out_dir(out_dir).run(); +} From 0eda44baacd49aff0b9bac6a00cdc56b6ad909db Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 28 Apr 2026 12:00:48 +0200 Subject: [PATCH 43/45] Delete the 12 year old fixme --- library/core/src/option.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d4dd33b948193..02cd88a6a4340 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -40,9 +40,6 @@ //! } //! ``` //! -// -// FIXME: Show how `Option` is used in practice, with lots of methods -// //! # Options and pointers ("nullable" pointers) //! //! Rust's pointer types must always point to a valid location; there are From 62ee4cdaa427c4ff187d98f5d383c7da513b97c8 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 28 Apr 2026 13:21:22 +0100 Subject: [PATCH 44/45] remove review queue triagebot mentions --- triagebot.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 9c69061c7b8cf..33ef3d097e618 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -940,10 +940,6 @@ Issue #{number} "{title}" has been added. # Mentions # ------------------------------------------------------------------------------ -[mentions."triagebot.toml"] -message = "`triagebot.toml` has been modified, there may have been changes to the review queue." -cc = ["@davidtwco", "@wesleywiser"] - [mentions."compiler/rustc_codegen_cranelift"] message = "The Cranelift subtree was changed" cc = ["@bjorn3"] From aef93ca43af9464ce2efb8678df70444770c2c70 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 28 Apr 2026 15:16:49 +0000 Subject: [PATCH 45/45] Document that CFI diverges from Rust wrt. ABI-compatibility rules --- library/core/src/primitive_docs.rs | 5 ++- .../src/compiler-flags/sanitizer.md | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 3a4e1e657a3da..48bf57356b575 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1794,6 +1794,7 @@ mod prim_ref {} /// have different sizes. /// /// ### ABI compatibility +/// [ABI compatibility]: #abi-compatibility /// /// Generally, when a function is declared with one signature and called via a function pointer with /// a different signature, the two signatures must be *ABI-compatible* or else calling the function @@ -1831,7 +1832,7 @@ mod prim_ref {} /// - `*const T`, `*mut T`, `&T`, `&mut T`, `Box` (specifically, only `Box`), and /// `NonNull` are all ABI-compatible with each other for all `T`. They are also ABI-compatible /// with each other for _different_ `T` if they have the same metadata type (`::Metadata`). +/// Pointee>::Metadata`). However, see the [Control Flow Integrity][cfi-docs] docs for caveats. /// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is /// ABI-compatible with the `iN` integer type of the same size. /// - `char` is ABI-compatible with `u32`. @@ -1890,6 +1891,8 @@ mod prim_ref {} /// Behavior since transmuting `None::>` to `NonZero` violates the non-zero /// requirement. /// +/// [cfi-docs]: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity +/// /// ### Trait implementations /// /// In this documentation the shorthand `fn(T₁, T₂, …, Tₙ)` is used to represent non-variadic diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index b0f6c97ff5a73..5bd518b14154b 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -246,6 +246,37 @@ Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI. See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. +## Divergence from the Rust ABI + +There are some caveats to [the ABI-compatibility rules for Rust-to-Rust +calls][rust-abi] due to how the CFI sanitizer is implemented. CFI is a tool +that can be used to validate that dynamic function calls respect the ABI, but +due to its C/C++ origins, it disagrees with the above documented guarantees in +a few ways, see below. As CFI is unstable, the details may change in the +future. + +When running the CFI sanitizer, pointer types are only ABI-compatible if the +target type and mutability is the same. This means that `*mut String` and `*mut +i32` are incompatible when using CFI. It also means that `*mut i32` is +incompatible with `*const i32`. The `NonNull<_>` and `Box<_>` pointer types are +currently considered immutable under CFI. For non-primitive target types, CFI +uses the name of the type for its compatibility check. + +When not using the `-Zsanitizer-cfi-normalize-integers` flag, the CFI sanitizer +further restricts the rules by considering `usize`/`isize` incompatible with +the `uN`/`iN` integer type of the same size. + +Unlike other cases where the function ABI is violated, function calls that +violate the CFI-specific ABI-compatibility rules are not undefined behavior. +They are guaranteed to either function correctly, or to crash the program. + +This section only covers cases where CFI disagrees with the ABI-compatibility +rules for Rust-to-Rust calls. It is not meant to be a complete explanation of +how CFI works, and details important for C-to-Rust or Rust-to-C calls are +omitted. + +[rust-abi]: https://doc.rust-lang.org/stable/std/primitive.fn.html#abi-compatibility + ## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination ```rust