From e101e383d0580e642548a5e935a9ff844339159a Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Sun, 29 Jun 2025 07:06:25 +0000 Subject: [PATCH 01/36] std_detect: Tidying of slice length We don't need to put the length of the `riscv_hwprobe` array into a variable. This commit removes that variable and gives the length of the output slice to the `__riscv_hwprobe` directly. --- library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs index 5506ff31fc792..e044d5f15412f 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs @@ -124,8 +124,7 @@ fn _riscv_hwprobe(out: &mut [riscv_hwprobe]) -> bool { } } - let len = out.len(); - unsafe { __riscv_hwprobe(out.as_mut_ptr(), len, 0, ptr::null_mut(), 0) == 0 } + unsafe { __riscv_hwprobe(out.as_mut_ptr(), out.len(), 0, ptr::null_mut(), 0) == 0 } } /// Read list of supported features from (1) the auxiliary vector From bb2d169700574d196f51b6a253e1a15c9b144c6d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 5 Jul 2025 10:57:05 +0200 Subject: [PATCH 02/36] use `is_multiple_of` to check if an addr is aligned --- library/stdarch/crates/core_arch/src/powerpc/macros.rs | 2 ++ library/stdarch/crates/core_arch/src/s390x/macros.rs | 2 ++ library/stdarch/crates/core_arch/src/s390x/vector.rs | 4 ++-- library/stdarch/crates/core_arch/src/wasm32/simd128.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/cmpxchg16b.rs | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/powerpc/macros.rs b/library/stdarch/crates/core_arch/src/powerpc/macros.rs index af47494e8fb40..24d86f1018c8f 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/macros.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/macros.rs @@ -278,6 +278,7 @@ macro_rules! impl_from { ($s: ident) => { #[unstable(feature = "stdarch_powerpc", issue = "111145")] impl From<$s> for s_t_l!($s) { + #[inline] fn from (v: $s) -> Self { unsafe { transmute(v) @@ -297,6 +298,7 @@ macro_rules! impl_neg { #[unstable(feature = "stdarch_powerpc", issue = "111145")] impl crate::ops::Neg for s_t_l!($s) { type Output = s_t_l!($s); + #[inline] fn neg(self) -> Self::Output { unsafe { simd_neg(self) } } diff --git a/library/stdarch/crates/core_arch/src/s390x/macros.rs b/library/stdarch/crates/core_arch/src/s390x/macros.rs index 4f0f84ec912b7..26afbaa45a741 100644 --- a/library/stdarch/crates/core_arch/src/s390x/macros.rs +++ b/library/stdarch/crates/core_arch/src/s390x/macros.rs @@ -435,6 +435,7 @@ macro_rules! impl_from { ($s: ident) => { #[unstable(feature = "stdarch_s390x", issue = "135681")] impl From<$s> for s_t_l!($s) { + #[inline] fn from (v: $s) -> Self { unsafe { transmute(v) @@ -454,6 +455,7 @@ macro_rules! impl_neg { #[unstable(feature = "stdarch_s390x", issue = "135681")] impl crate::ops::Neg for s_t_l!($s) { type Output = s_t_l!($s); + #[inline] fn neg(self) -> Self::Output { unsafe { simd_neg(self) } } diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index ae5c37ce0178b..101de7010699d 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -51,7 +51,7 @@ types! { pub struct vector_double(2 x f64); } -#[repr(packed)] +#[repr(C, packed)] struct PackedTuple { x: T, y: U, @@ -4787,7 +4787,7 @@ pub unsafe fn vec_splat_s8() -> vector_signed_char { #[unstable(feature = "stdarch_s390x", issue = "135681")] #[cfg_attr(test, assert_instr(vrepih, IMM = 42))] pub unsafe fn vec_splat_s16() -> vector_signed_short { - vector_signed_short([IMM as i16; 8]) + vector_signed_short([IMM; 8]) } /// Vector Splat Signed Word diff --git a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs index fc0d7723fa014..108bc3125c5f3 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs @@ -141,7 +141,7 @@ unsafe extern "unadjusted" { fn llvm_f64x2_max(x: simd::f64x2, y: simd::f64x2) -> simd::f64x2; } -#[repr(packed)] +#[repr(C, packed)] #[derive(Copy)] struct Unaligned(T); diff --git a/library/stdarch/crates/core_arch/src/x86_64/cmpxchg16b.rs b/library/stdarch/crates/core_arch/src/x86_64/cmpxchg16b.rs index 46a008245bf82..d3e7f62903b32 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/cmpxchg16b.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/cmpxchg16b.rs @@ -48,7 +48,7 @@ pub unsafe fn cmpxchg16b( success: Ordering, failure: Ordering, ) -> u128 { - debug_assert!(dst as usize % 16 == 0); + debug_assert!(dst.addr().is_multiple_of(16)); let res = crate::sync::atomic::atomic_compare_exchange(dst, old, new, success, failure); res.unwrap_or_else(|x| x) From e8d9e80ac649599a6c7d8588cde3e1c87d154781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 26 Jun 2025 11:34:44 +0200 Subject: [PATCH 03/36] Add empty rust-version file --- library/stdarch/rust-version | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 library/stdarch/rust-version diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version new file mode 100644 index 0000000000000..e69de29bb2d1d From f697f81fc900d43b3aa574ccc961e94589bb4fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 26 Jun 2025 11:37:10 +0200 Subject: [PATCH 04/36] Add josh synchronization scripts --- library/stdarch/README.md | 49 +++ library/stdarch/josh-sync/Cargo.lock | 437 ++++++++++++++++++++++++++ library/stdarch/josh-sync/Cargo.toml | 11 + library/stdarch/josh-sync/README.md | 4 + library/stdarch/josh-sync/src/main.rs | 41 +++ library/stdarch/josh-sync/src/sync.rs | 275 ++++++++++++++++ 6 files changed, 817 insertions(+) create mode 100644 library/stdarch/josh-sync/Cargo.lock create mode 100644 library/stdarch/josh-sync/Cargo.toml create mode 100644 library/stdarch/josh-sync/README.md create mode 100644 library/stdarch/josh-sync/src/main.rs create mode 100644 library/stdarch/josh-sync/src/sync.rs diff --git a/library/stdarch/README.md b/library/stdarch/README.md index 70ec256e681e0..22d8e2357c216 100644 --- a/library/stdarch/README.md +++ b/library/stdarch/README.md @@ -16,3 +16,52 @@ This repository contains two main crates: The `std::simd` component now lives in the [`packed_simd_2`](https://github.com/rust-lang/packed_simd) crate. + +## Synchronizing josh subtree with rustc + +This repository is linked to `rust-lang/rust` as a [josh](https://josh-project.github.io/josh/intro.html) subtree. You can use the following commands to synchronize the subtree in both directions. + +You'll need to install `josh-proxy` locally via + +``` +cargo install josh-proxy --git https://github.com/josh-project/josh --tag r24.10.04 +``` +Older versions of `josh-proxy` may not round trip commits losslessly so it is important to install this exact version. + +### Pull changes from `rust-lang/rust` into this repository + +1) Checkout a new branch that will be used to create a PR into `rust-lang/stdarch` +2) Run the pull command + ``` + cargo run --manifest-path josh-sync/Cargo.toml rustc-pull + ``` +3) Push the branch to your fork and create a PR into `stdarch` + +### Push changes from this repository into `rust-lang/rust` + +NOTE: If you use Git protocol to push to your fork of `rust-lang/rust`, +ensure that you have this entry in your Git config, +else the 2 steps that follow would prompt for a username and password: + +``` +[url "git@github.com:"] +insteadOf = "https://github.com/" +``` + +1) Run the push command to create a branch named `` in a `rustc` fork under the `` account + ``` + cargo run --manifest-path josh-sync/Cargo.toml rustc-push + ``` +2) Create a PR from `` into `rust-lang/rust` + +#### Minimal git config + +For simplicity (ease of implementation purposes), the josh-sync script simply calls out to system git. This means that the git invocation may be influenced by global (or local) git configuration. + +You may observe "Nothing to pull" even if you *know* rustc-pull has something to pull if your global git config sets `fetch.prunetags = true` (and possibly other configurations may cause unexpected outcomes). + +To minimize the likelihood of this happening, you may wish to keep a separate *minimal* git config that *only* has `[user]` entries from global git config, then repoint system git to use the minimal git config instead. E.g. + +``` +GIT_CONFIG_GLOBAL=/path/to/minimal/gitconfig GIT_CONFIG_SYSTEM='' cargo run --manifest-path josh-sync/Cargo.toml -- rustc-pull +``` diff --git a/library/stdarch/josh-sync/Cargo.lock b/library/stdarch/josh-sync/Cargo.lock new file mode 100644 index 0000000000000..f3d1fd0d1fe1f --- /dev/null +++ b/library/stdarch/josh-sync/Cargo.lock @@ -0,0 +1,437 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "clap" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "josh-sync" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "directories", + "xshell", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libredox" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xshell" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d" +dependencies = [ + "xshell-macros", +] + +[[package]] +name = "xshell-macros" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547" diff --git a/library/stdarch/josh-sync/Cargo.toml b/library/stdarch/josh-sync/Cargo.toml new file mode 100644 index 0000000000000..b4dbde9e875e0 --- /dev/null +++ b/library/stdarch/josh-sync/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "josh-sync" +edition = "2024" + +[dependencies] +anyhow = "1.0.95" +clap = { version = "4.5.21", features = ["derive"] } +directories = "5" +xshell = "0.2.6" + +[workspace] diff --git a/library/stdarch/josh-sync/README.md b/library/stdarch/josh-sync/README.md new file mode 100644 index 0000000000000..a3dd876e8b87b --- /dev/null +++ b/library/stdarch/josh-sync/README.md @@ -0,0 +1,4 @@ +# Git josh sync +This utility serves for syncing the josh git subtree to and from the rust-lang/rust repository. + +See CLI help for usage. diff --git a/library/stdarch/josh-sync/src/main.rs b/library/stdarch/josh-sync/src/main.rs new file mode 100644 index 0000000000000..2ec061a43b79c --- /dev/null +++ b/library/stdarch/josh-sync/src/main.rs @@ -0,0 +1,41 @@ +use clap::Parser; + +use crate::sync::{GitSync, RustcPullError}; + +mod sync; + +#[derive(clap::Parser)] +enum Args { + /// Pull changes from the main `rustc` repository. + /// This creates new commits that should be then merged into `stdarch`. + RustcPull, + /// Push changes from `stdarch` to the given `branch` of a `rustc` fork under the given + /// GitHub `username`. + /// The pushed branch should then be merged into the `rustc` repository. + RustcPush { branch: String, github_username: String }, +} + +fn main() -> anyhow::Result<()> { + let args = Args::parse(); + let sync = GitSync::from_current_dir()?; + match args { + Args::RustcPull => { + if let Err(error) = sync.rustc_pull(None) { + match error { + RustcPullError::NothingToPull => { + eprintln!("Nothing to pull"); + std::process::exit(2); + } + RustcPullError::PullFailed(error) => { + eprintln!("Pull failure: {error:?}"); + std::process::exit(1); + } + } + } + } + Args::RustcPush { github_username, branch } => { + sync.rustc_push(github_username, branch)?; + } + } + Ok(()) +} diff --git a/library/stdarch/josh-sync/src/sync.rs b/library/stdarch/josh-sync/src/sync.rs new file mode 100644 index 0000000000000..f868a7b48ea31 --- /dev/null +++ b/library/stdarch/josh-sync/src/sync.rs @@ -0,0 +1,275 @@ +use std::io::Write; +use std::ops::Not; +use std::path::PathBuf; +use std::time::Duration; +use std::{env, net, process}; + +use anyhow::{Context, anyhow, bail}; +use xshell::{Shell, cmd}; + +/// Used for rustc syncs. +const JOSH_FILTER: &str = ":/library/stdarch"; +const JOSH_PORT: u16 = 42042; +const UPSTREAM_REPO: &str = "rust-lang/rust"; + +pub enum RustcPullError { + /// No changes are available to be pulled. + NothingToPull, + /// A rustc-pull has failed, probably a git operation error has occurred. + PullFailed(anyhow::Error), +} + +impl From for RustcPullError +where + E: Into, +{ + fn from(error: E) -> Self { + Self::PullFailed(error.into()) + } +} + +pub struct GitSync { + dir: PathBuf, +} + +/// This code was adapted from the miri repository +/// (https://github.com/rust-lang/miri/blob/6a68a79f38064c3bc30617cca4bdbfb2c336b140/miri-script/src/commands.rs#L236). +impl GitSync { + pub fn from_current_dir() -> anyhow::Result { + Ok(Self { dir: std::env::current_dir()? }) + } + + pub fn rustc_pull(&self, commit: Option) -> Result<(), RustcPullError> { + let sh = Shell::new()?; + sh.change_dir(&self.dir); + let commit = commit.map(Ok).unwrap_or_else(|| { + let rust_repo_head = + cmd!(sh, "git ls-remote https://github.com/{UPSTREAM_REPO}/ HEAD").read()?; + rust_repo_head + .split_whitespace() + .next() + .map(|front| front.trim().to_owned()) + .ok_or_else(|| anyhow!("Could not obtain Rust repo HEAD from remote.")) + })?; + // Make sure the repo is clean. + if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() { + return Err(anyhow::anyhow!( + "working directory must be clean before performing rustc pull" + ) + .into()); + } + // Make sure josh is running. + let josh = Self::start_josh()?; + let josh_url = + format!("http://localhost:{JOSH_PORT}/{UPSTREAM_REPO}.git@{commit}{JOSH_FILTER}.git"); + + let previous_base_commit = sh.read_file("rust-version")?.trim().to_string(); + if previous_base_commit == commit { + return Err(RustcPullError::NothingToPull); + } + + // Update rust-version file. As a separate commit, since making it part of + // the merge has confused the heck out of josh in the past. + // We pass `--no-verify` to avoid running git hooks. + // We do this before the merge so that if there are merge conflicts, we have + // the right rust-version file while resolving them. + sh.write_file("rust-version", format!("{commit}\n"))?; + const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rustc"; + cmd!(sh, "git commit rust-version --no-verify -m {PREPARING_COMMIT_MESSAGE}") + .run() + .context("FAILED to commit rust-version file, something went wrong")?; + + // Fetch given rustc commit. + cmd!(sh, "git fetch {josh_url}") + .run() + .inspect_err(|_| { + // Try to un-do the previous `git commit`, to leave the repo in the state we found it. + cmd!(sh, "git reset --hard HEAD^") + .run() + .expect("FAILED to clean up again after failed `git fetch`, sorry for that"); + }) + .context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?; + + // This should not add any new root commits. So count those before and after merging. + let num_roots = || -> anyhow::Result { + Ok(cmd!(sh, "git rev-list HEAD --max-parents=0 --count") + .read() + .context("failed to determine the number of root commits")? + .parse::()?) + }; + let num_roots_before = num_roots()?; + + let sha = + cmd!(sh, "git rev-parse HEAD").output().context("FAILED to get current commit")?.stdout; + + // Merge the fetched commit. + const MERGE_COMMIT_MESSAGE: &str = "Merge from rustc"; + cmd!(sh, "git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}") + .run() + .context("FAILED to merge new commits, something went wrong")?; + + let current_sha = + cmd!(sh, "git rev-parse HEAD").output().context("FAILED to get current commit")?.stdout; + if current_sha == sha { + cmd!(sh, "git reset --hard HEAD^") + .run() + .expect("FAILED to clean up after creating the preparation commit"); + eprintln!( + "No merge was performed, no changes to pull were found. Rolled back the preparation commit." + ); + return Err(RustcPullError::NothingToPull); + } + + // Check that the number of roots did not increase. + if num_roots()? != num_roots_before { + return Err(anyhow::anyhow!( + "Josh created a new root commit. This is probably not the history you want." + ) + .into()); + } + + drop(josh); + Ok(()) + } + + pub fn rustc_push(&self, github_user: String, branch: String) -> anyhow::Result<()> { + let sh = Shell::new()?; + sh.change_dir(&self.dir); + let base = sh.read_file("rust-version")?.trim().to_owned(); + // Make sure the repo is clean. + if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() { + bail!("working directory must be clean before running `rustc-push`"); + } + // Make sure josh is running. + let josh = Self::start_josh()?; + let josh_url = + format!("http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git"); + + // Find a repo we can do our preparation in. + if let Ok(rustc_git) = env::var("RUSTC_GIT") { + // If rustc_git is `Some`, we'll use an existing fork for the branch updates. + sh.change_dir(rustc_git); + } else { + // Otherwise, do this in the local repo. + println!( + "This will pull a copy of the rust-lang/rust history into this checkout, growing it by about 1GB." + ); + print!( + "To avoid that, abort now and set the `RUSTC_GIT` environment variable to an existing rustc checkout. Proceed? [y/N] " + ); + std::io::stdout().flush()?; + let mut answer = String::new(); + std::io::stdin().read_line(&mut answer)?; + if answer.trim().to_lowercase() != "y" { + std::process::exit(1); + } + }; + // Prepare the branch. Pushing works much better if we use as base exactly + // the commit that we pulled from last time, so we use the `rust-version` + // file to find out which commit that would be. + println!("Preparing {github_user}/rust (base: {base})..."); + if cmd!(sh, "git fetch https://github.com/{github_user}/rust {branch}") + .ignore_stderr() + .read() + .is_ok() + { + println!( + "The branch '{branch}' seems to already exist in 'https://github.com/{github_user}/rust'. Please delete it and try again." + ); + std::process::exit(1); + } + cmd!(sh, "git fetch https://github.com/{UPSTREAM_REPO} {base}").run()?; + cmd!(sh, "git push https://github.com/{github_user}/rust {base}:refs/heads/{branch}") + .ignore_stdout() + .ignore_stderr() // silence the "create GitHub PR" message + .run()?; + println!(); + + // Do the actual push. + sh.change_dir(&self.dir); + println!("Pushing changes..."); + cmd!(sh, "git push {josh_url} HEAD:{branch}").run()?; + println!(); + + // Do a round-trip check to make sure the push worked as expected. + cmd!(sh, "git fetch {josh_url} {branch}").ignore_stderr().read()?; + let head = cmd!(sh, "git rev-parse HEAD").read()?; + let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?; + if head != fetch_head { + bail!( + "Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\ + Expected {head}, got {fetch_head}." + ); + } + println!( + "Confirmed that the push round-trips back to stdarch properly. Please create a rustc PR:" + ); + println!( + // Open PR with `subtree update` title to silence the `no-merges` triagebot check + " https://github.com/{UPSTREAM_REPO}/compare/{github_user}:{branch}?quick_pull=1&title=stdarch+subtree+update&body=r?+@ghost" + ); + + drop(josh); + Ok(()) + } + + fn start_josh() -> anyhow::Result { + // Determine cache directory. + let local_dir = { + let user_dirs = + directories::ProjectDirs::from("org", "rust-lang", "stdarch-josh").unwrap(); + user_dirs.cache_dir().to_owned() + }; + + // Start josh, silencing its output. + let mut cmd = process::Command::new("josh-proxy"); + cmd.arg("--local").arg(local_dir); + cmd.arg("--remote").arg("https://github.com"); + cmd.arg("--port").arg(JOSH_PORT.to_string()); + cmd.arg("--no-background"); + cmd.stdout(process::Stdio::null()); + cmd.stderr(process::Stdio::null()); + let josh = cmd.spawn().context("failed to start josh-proxy, make sure it is installed")?; + + // Create a wrapper that stops it on drop. + struct Josh(process::Child); + impl Drop for Josh { + fn drop(&mut self) { + #[cfg(unix)] + { + // Try to gracefully shut it down. + process::Command::new("kill") + .args(["-s", "INT", &self.0.id().to_string()]) + .output() + .expect("failed to SIGINT josh-proxy"); + // Sadly there is no "wait with timeout"... so we just give it some time to finish. + std::thread::sleep(Duration::from_millis(100)); + // Now hopefully it is gone. + if self.0.try_wait().expect("failed to wait for josh-proxy").is_some() { + return; + } + } + // If that didn't work (or we're not on Unix), kill it hard. + eprintln!( + "I have to kill josh-proxy the hard way, let's hope this does not break anything." + ); + self.0.kill().expect("failed to SIGKILL josh-proxy"); + } + } + + // Wait until the port is open. We try every 10ms until 1s passed. + for _ in 0..100 { + // This will generally fail immediately when the port is still closed. + let josh_ready = net::TcpStream::connect_timeout( + &net::SocketAddr::from(([127, 0, 0, 1], JOSH_PORT)), + Duration::from_millis(1), + ); + if josh_ready.is_ok() { + return Ok(Josh(josh)); + } + // Not ready yet. + std::thread::sleep(Duration::from_millis(10)); + } + bail!("Even after waiting for 1s, josh-proxy is still not available.") + } +} From 8ae4e6a566f2a5ef8998f66d2035837e9d767826 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 30 Jun 2025 11:05:48 +0200 Subject: [PATCH 05/36] Update stabilization version of certain x86 intrinsics to 1.89 These were left as `CURRENT_RUSTC_VERSION` in the submodule. --- .../stdarch/crates/core_arch/src/x86/kl.rs | 22 +++++++++---------- .../stdarch/crates/core_arch/src/x86/mod.rs | 2 +- .../stdarch/crates/core_arch/src/x86/sha.rs | 20 ++++++++--------- .../crates/std_detect/src/detect/arch/x86.rs | 10 ++++----- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/kl.rs b/library/stdarch/crates/core_arch/src/x86/kl.rs index eb9eb83f4115c..26e5a46c62934 100644 --- a/library/stdarch/crates/core_arch/src/x86/kl.rs +++ b/library/stdarch/crates/core_arch/src/x86/kl.rs @@ -127,7 +127,7 @@ unsafe extern "unadjusted" { /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadiwkey) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(loadiwkey))] pub unsafe fn _mm_loadiwkey( control: u32, @@ -153,7 +153,7 @@ pub unsafe fn _mm_loadiwkey( /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_encodekey128_u32) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(encodekey128))] pub unsafe fn _mm_encodekey128_u32(key_params: u32, key: __m128i, handle: *mut u8) -> u32 { let EncodeKey128Output(control, key0, key1, key2, _, _, _) = encodekey128(key_params, key); @@ -176,7 +176,7 @@ pub unsafe fn _mm_encodekey128_u32(key_params: u32, key: __m128i, handle: *mut u /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_encodekey256_u32) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(encodekey256))] pub unsafe fn _mm_encodekey256_u32( key_params: u32, @@ -198,7 +198,7 @@ pub unsafe fn _mm_encodekey256_u32( /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc128kl_u8) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesenc128kl))] pub unsafe fn _mm_aesenc128kl_u8(output: *mut __m128i, input: __m128i, handle: *const u8) -> u8 { let AesOutput(status, result) = aesenc128kl(input, handle); @@ -214,7 +214,7 @@ pub unsafe fn _mm_aesenc128kl_u8(output: *mut __m128i, input: __m128i, handle: * /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec128kl_u8) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesdec128kl))] pub unsafe fn _mm_aesdec128kl_u8(output: *mut __m128i, input: __m128i, handle: *const u8) -> u8 { let AesOutput(status, result) = aesdec128kl(input, handle); @@ -230,7 +230,7 @@ pub unsafe fn _mm_aesdec128kl_u8(output: *mut __m128i, input: __m128i, handle: * /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc256kl_u8) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesenc256kl))] pub unsafe fn _mm_aesenc256kl_u8(output: *mut __m128i, input: __m128i, handle: *const u8) -> u8 { let AesOutput(status, result) = aesenc256kl(input, handle); @@ -246,7 +246,7 @@ pub unsafe fn _mm_aesenc256kl_u8(output: *mut __m128i, input: __m128i, handle: * /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec256kl_u8) #[inline] #[target_feature(enable = "kl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesdec256kl))] pub unsafe fn _mm_aesdec256kl_u8(output: *mut __m128i, input: __m128i, handle: *const u8) -> u8 { let AesOutput(status, result) = aesdec256kl(input, handle); @@ -262,7 +262,7 @@ pub unsafe fn _mm_aesdec256kl_u8(output: *mut __m128i, input: __m128i, handle: * /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesencwide128kl_u8) #[inline] #[target_feature(enable = "widekl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesencwide128kl))] pub unsafe fn _mm_aesencwide128kl_u8( output: *mut __m128i, @@ -285,7 +285,7 @@ pub unsafe fn _mm_aesencwide128kl_u8( /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdecwide128kl_u8) #[inline] #[target_feature(enable = "widekl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesdecwide128kl))] pub unsafe fn _mm_aesdecwide128kl_u8( output: *mut __m128i, @@ -308,7 +308,7 @@ pub unsafe fn _mm_aesdecwide128kl_u8( /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesencwide256kl_u8) #[inline] #[target_feature(enable = "widekl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesencwide256kl))] pub unsafe fn _mm_aesencwide256kl_u8( output: *mut __m128i, @@ -331,7 +331,7 @@ pub unsafe fn _mm_aesencwide256kl_u8( /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdecwide256kl_u8) #[inline] #[target_feature(enable = "widekl")] -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] #[cfg_attr(test, assert_instr(aesdecwide256kl))] pub unsafe fn _mm_aesdecwide256kl_u8( output: *mut __m128i, diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs index 8897258c7dc24..79a593e647f13 100644 --- a/library/stdarch/crates/core_arch/src/x86/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86/mod.rs @@ -772,5 +772,5 @@ mod avx512fp16; pub use self::avx512fp16::*; mod kl; -#[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "keylocker_x86", since = "1.89.0")] pub use self::kl::*; diff --git a/library/stdarch/crates/core_arch/src/x86/sha.rs b/library/stdarch/crates/core_arch/src/x86/sha.rs index da568c449a6be..9ad1a9f14c155 100644 --- a/library/stdarch/crates/core_arch/src/x86/sha.rs +++ b/library/stdarch/crates/core_arch/src/x86/sha.rs @@ -146,7 +146,7 @@ pub fn _mm_sha256rnds2_epu32(a: __m128i, b: __m128i, k: __m128i) -> __m128i { #[inline] #[target_feature(enable = "sha512,avx")] #[cfg_attr(test, assert_instr(vsha512msg1))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm256_sha512msg1_epi64(a: __m256i, b: __m128i) -> __m256i { unsafe { transmute(vsha512msg1(a.as_i64x4(), b.as_i64x2())) } } @@ -159,7 +159,7 @@ pub fn _mm256_sha512msg1_epi64(a: __m256i, b: __m128i) -> __m256i { #[inline] #[target_feature(enable = "sha512,avx")] #[cfg_attr(test, assert_instr(vsha512msg2))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm256_sha512msg2_epi64(a: __m256i, b: __m256i) -> __m256i { unsafe { transmute(vsha512msg2(a.as_i64x4(), b.as_i64x4())) } } @@ -175,7 +175,7 @@ pub fn _mm256_sha512msg2_epi64(a: __m256i, b: __m256i) -> __m256i { #[inline] #[target_feature(enable = "sha512,avx")] #[cfg_attr(test, assert_instr(vsha512rnds2))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm256_sha512rnds2_epi64(a: __m256i, b: __m256i, k: __m128i) -> __m256i { unsafe { transmute(vsha512rnds2(a.as_i64x4(), b.as_i64x4(), k.as_i64x2())) } } @@ -188,7 +188,7 @@ pub fn _mm256_sha512rnds2_epi64(a: __m256i, b: __m256i, k: __m128i) -> __m256i { #[inline] #[target_feature(enable = "sm3,avx")] #[cfg_attr(test, assert_instr(vsm3msg1))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm_sm3msg1_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { unsafe { transmute(vsm3msg1(a.as_i32x4(), b.as_i32x4(), c.as_i32x4())) } } @@ -201,7 +201,7 @@ pub fn _mm_sm3msg1_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { #[inline] #[target_feature(enable = "sm3,avx")] #[cfg_attr(test, assert_instr(vsm3msg2))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm_sm3msg2_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { unsafe { transmute(vsm3msg2(a.as_i32x4(), b.as_i32x4(), c.as_i32x4())) } } @@ -219,7 +219,7 @@ pub fn _mm_sm3msg2_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { #[target_feature(enable = "sm3,avx")] #[cfg_attr(test, assert_instr(vsm3rnds2, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm_sm3rnds2_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { static_assert!( IMM8 == (IMM8 & 0x3e), @@ -235,7 +235,7 @@ pub fn _mm_sm3rnds2_epi32(a: __m128i, b: __m128i, c: __m128i) - #[inline] #[target_feature(enable = "sm4,avx")] #[cfg_attr(test, assert_instr(vsm4key4))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm_sm4key4_epi32(a: __m128i, b: __m128i) -> __m128i { unsafe { transmute(vsm4key4128(a.as_i32x4(), b.as_i32x4())) } } @@ -247,7 +247,7 @@ pub fn _mm_sm4key4_epi32(a: __m128i, b: __m128i) -> __m128i { #[inline] #[target_feature(enable = "sm4,avx")] #[cfg_attr(test, assert_instr(vsm4key4))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm256_sm4key4_epi32(a: __m256i, b: __m256i) -> __m256i { unsafe { transmute(vsm4key4256(a.as_i32x8(), b.as_i32x8())) } } @@ -259,7 +259,7 @@ pub fn _mm256_sm4key4_epi32(a: __m256i, b: __m256i) -> __m256i { #[inline] #[target_feature(enable = "sm4,avx")] #[cfg_attr(test, assert_instr(vsm4rnds4))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm_sm4rnds4_epi32(a: __m128i, b: __m128i) -> __m128i { unsafe { transmute(vsm4rnds4128(a.as_i32x4(), b.as_i32x4())) } } @@ -271,7 +271,7 @@ pub fn _mm_sm4rnds4_epi32(a: __m128i, b: __m128i) -> __m128i { #[inline] #[target_feature(enable = "sm4,avx")] #[cfg_attr(test, assert_instr(vsm4rnds4))] -#[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "sha512_sm_x86", since = "1.89.0")] pub fn _mm256_sm4rnds4_epi32(a: __m256i, b: __m256i) -> __m256i { unsafe { transmute(vsm4rnds4256(a.as_i32x8(), b.as_i32x8())) } } diff --git a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs index f23cfc334170f..28b3e3cfb35b7 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs @@ -157,11 +157,11 @@ features! { /// AVX (Advanced Vector Extensions) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx2: "avx2"; /// AVX2 (Advanced Vector Extensions 2) - @FEATURE: #[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] sha512: "sha512"; + @FEATURE: #[stable(feature = "sha512_sm_x86", since = "1.89.0")] sha512: "sha512"; /// SHA512 - @FEATURE: #[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] sm3: "sm3"; + @FEATURE: #[stable(feature = "sha512_sm_x86", since = "1.89.0")] sm3: "sm3"; /// SM3 - @FEATURE: #[stable(feature = "sha512_sm_x86", since = "CURRENT_RUSTC_VERSION")] sm4: "sm4"; + @FEATURE: #[stable(feature = "sha512_sm_x86", since = "1.89.0")] sm4: "sm4"; /// SM4 @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512f: "avx512f" ; /// AVX-512 F (Foundation) @@ -259,9 +259,9 @@ features! { /// XSAVEC (Save Processor Extended States Compacted) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] cmpxchg16b: "cmpxchg16b"; /// CMPXCH16B (16-byte compare-and-swap instruction) - @FEATURE: #[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] kl: "kl"; + @FEATURE: #[stable(feature = "keylocker_x86", since = "1.89.0")] kl: "kl"; /// Intel Key Locker - @FEATURE: #[stable(feature = "keylocker_x86", since = "CURRENT_RUSTC_VERSION")] widekl: "widekl"; + @FEATURE: #[stable(feature = "keylocker_x86", since = "1.89.0")] widekl: "widekl"; /// Intel Key Locker Wide @FEATURE: #[stable(feature = "simd_x86_adx", since = "1.33.0")] adx: "adx"; /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions) From e46d2207bdfd29b6ddc94c5e0fb44558b1f2b4bb Mon Sep 17 00:00:00 2001 From: ltdk Date: Mon, 30 Jun 2025 17:49:49 -0400 Subject: [PATCH 06/36] Use simd_extract! macro instead of calling simd_extract directly --- library/stdarch/crates/core_arch/src/x86/avx512f.rs | 8 ++++---- library/stdarch/crates/core_arch/src/x86/avx512fp16.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index dd224616764d6..d53f83c0a10bc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -33248,7 +33248,7 @@ pub fn _mm512_reduce_add_ps(a: __m512) -> f32 { ); let a = _mm_add_ps(_mm256_extractf128_ps::<0>(a), _mm256_extractf128_ps::<1>(a)); let a = _mm_add_ps(a, simd_shuffle!(a, a, [2, 3, 0, 1])); - simd_extract::<_, f32>(a, 0) + simd_extract::<_, f32>(a, 1) + simd_extract!(a, 0, f32) + simd_extract!(a, 1, f32) } } @@ -33275,7 +33275,7 @@ pub fn _mm512_reduce_add_pd(a: __m512d) -> f64 { _mm512_extractf64x4_pd::<1>(a), ); let a = _mm_add_pd(_mm256_extractf128_pd::<0>(a), _mm256_extractf128_pd::<1>(a)); - simd_extract::<_, f64>(a, 0) + simd_extract::<_, f64>(a, 1) + simd_extract!(a, 0, f64) + simd_extract!(a, 1, f64) } } @@ -33356,7 +33356,7 @@ pub fn _mm512_reduce_mul_ps(a: __m512) -> f32 { ); let a = _mm_mul_ps(_mm256_extractf128_ps::<0>(a), _mm256_extractf128_ps::<1>(a)); let a = _mm_mul_ps(a, simd_shuffle!(a, a, [2, 3, 0, 1])); - simd_extract::<_, f32>(a, 0) * simd_extract::<_, f32>(a, 1) + simd_extract!(a, 0, f32) * simd_extract!(a, 1, f32) } } @@ -33383,7 +33383,7 @@ pub fn _mm512_reduce_mul_pd(a: __m512d) -> f64 { _mm512_extractf64x4_pd::<1>(a), ); let a = _mm_mul_pd(_mm256_extractf128_pd::<0>(a), _mm256_extractf128_pd::<1>(a)); - simd_extract::<_, f64>(a, 0) * simd_extract::<_, f64>(a, 1) + simd_extract!(a, 0, f64) * simd_extract!(a, 1, f64) } } diff --git a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs index 0a81a0581f97a..8c914803c665d 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs @@ -11032,7 +11032,7 @@ pub fn _mm_reduce_add_ph(a: __m128h) -> f16 { let a = _mm_add_ph(a, b); let b = simd_shuffle!(a, a, [2, 3, 0, 1, 4, 5, 6, 7]); let a = _mm_add_ph(a, b); - simd_extract::<_, f16>(a, 0) + simd_extract::<_, f16>(a, 1) + simd_extract!(a, 0, f16) + simd_extract!(a, 1, f16) } } @@ -11085,7 +11085,7 @@ pub fn _mm_reduce_mul_ph(a: __m128h) -> f16 { let a = _mm_mul_ph(a, b); let b = simd_shuffle!(a, a, [2, 3, 0, 1, 4, 5, 6, 7]); let a = _mm_mul_ph(a, b); - simd_extract::<_, f16>(a, 0) * simd_extract::<_, f16>(a, 1) + simd_extract!(a, 0, f16) * simd_extract!(a, 1, f16) } } From 600497f3ed3e514599d2808814410f832788dd42 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Mon, 23 Jun 2025 15:37:42 -0400 Subject: [PATCH 07/36] Mark `avx` broadcast intrinsics as safe --- library/stdarch/crates/core_arch/src/x86/avx.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index df1cb63be30f0..24e0cf6ba1afb 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -1258,7 +1258,7 @@ pub fn _mm256_permute2f128_si256(a: __m256i, b: __m256i) -> __m #[cfg_attr(test, assert_instr(vbroadcastss))] #[stable(feature = "simd_x86", since = "1.27.0")] #[allow(clippy::trivially_copy_pass_by_ref)] -pub unsafe fn _mm256_broadcast_ss(f: &f32) -> __m256 { +pub fn _mm256_broadcast_ss(f: &f32) -> __m256 { _mm256_set1_ps(*f) } @@ -1271,7 +1271,7 @@ pub unsafe fn _mm256_broadcast_ss(f: &f32) -> __m256 { #[cfg_attr(test, assert_instr(vbroadcastss))] #[stable(feature = "simd_x86", since = "1.27.0")] #[allow(clippy::trivially_copy_pass_by_ref)] -pub unsafe fn _mm_broadcast_ss(f: &f32) -> __m128 { +pub fn _mm_broadcast_ss(f: &f32) -> __m128 { _mm_set1_ps(*f) } @@ -1284,7 +1284,7 @@ pub unsafe fn _mm_broadcast_ss(f: &f32) -> __m128 { #[cfg_attr(test, assert_instr(vbroadcastsd))] #[stable(feature = "simd_x86", since = "1.27.0")] #[allow(clippy::trivially_copy_pass_by_ref)] -pub unsafe fn _mm256_broadcast_sd(f: &f64) -> __m256d { +pub fn _mm256_broadcast_sd(f: &f64) -> __m256d { _mm256_set1_pd(*f) } @@ -1296,8 +1296,8 @@ pub unsafe fn _mm256_broadcast_sd(f: &f64) -> __m256d { #[target_feature(enable = "avx")] #[cfg_attr(test, assert_instr(vbroadcastf128))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub unsafe fn _mm256_broadcast_ps(a: &__m128) -> __m256 { - simd_shuffle!(*a, _mm_setzero_ps(), [0, 1, 2, 3, 0, 1, 2, 3]) +pub fn _mm256_broadcast_ps(a: &__m128) -> __m256 { + unsafe { simd_shuffle!(*a, _mm_setzero_ps(), [0, 1, 2, 3, 0, 1, 2, 3]) } } /// Broadcasts 128 bits from memory (composed of 2 packed double-precision @@ -1308,8 +1308,8 @@ pub unsafe fn _mm256_broadcast_ps(a: &__m128) -> __m256 { #[target_feature(enable = "avx")] #[cfg_attr(test, assert_instr(vbroadcastf128))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub unsafe fn _mm256_broadcast_pd(a: &__m128d) -> __m256d { - simd_shuffle!(*a, _mm_setzero_pd(), [0, 1, 0, 1]) +pub fn _mm256_broadcast_pd(a: &__m128d) -> __m256d { + unsafe { simd_shuffle!(*a, _mm_setzero_pd(), [0, 1, 0, 1]) } } /// Copies `a` to result, then inserts 128 bits (composed of 4 packed From b5350036080f5183522f1c00d190a9b07850da24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 4 Jul 2025 09:25:10 +0200 Subject: [PATCH 08/36] Remove std-detect dev dependency in core_arch --- library/stdarch/Cargo.lock | 1 - library/stdarch/crates/core_arch/Cargo.toml | 1 - library/stdarch/crates/core_arch/src/lib.rs | 4 +--- library/stdarch/crates/simd-test-macro/src/lib.rs | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 3b76eed770bd0..80f424dfdd8da 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -147,7 +147,6 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" name = "core_arch" version = "0.1.5" dependencies = [ - "std_detect", "stdarch-test", "syscalls", ] diff --git a/library/stdarch/crates/core_arch/Cargo.toml b/library/stdarch/crates/core_arch/Cargo.toml index f4bd5fc552afe..670447a2d5a8b 100644 --- a/library/stdarch/crates/core_arch/Cargo.toml +++ b/library/stdarch/crates/core_arch/Cargo.toml @@ -22,7 +22,6 @@ maintenance = { status = "experimental" } [dev-dependencies] stdarch-test = { version = "0.*", path = "../stdarch-test" } -std_detect = { version = "0.*", path = "../std_detect" } [target.'cfg(all(target_arch = "x86_64", target_os = "linux"))'.dev-dependencies] syscalls = { version = "0.6.18", default-features = false } diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 340c4c510d784..c58580f641780 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -75,9 +75,7 @@ #[cfg(test)] #[macro_use] extern crate std; -#[cfg(test)] -#[macro_use] -extern crate std_detect; + #[path = "mod.rs"] mod core_arch; diff --git a/library/stdarch/crates/simd-test-macro/src/lib.rs b/library/stdarch/crates/simd-test-macro/src/lib.rs index 18e4747d94d91..855e969e1eb79 100644 --- a/library/stdarch/crates/simd-test-macro/src/lib.rs +++ b/library/stdarch/crates/simd-test-macro/src/lib.rs @@ -89,7 +89,7 @@ pub fn simd_test( for feature in target_features { let q = quote_spanned! { proc_macro2::Span::call_site() => - if !#macro_test!(#feature) { + if !::std::arch::#macro_test!(#feature) { missing_features.push(#feature); } }; From 816f0297391fb0c45a429a118264de31cb531162 Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Sun, 29 Jun 2025 10:01:27 +0200 Subject: [PATCH 09/36] Update README.md - Update ui.md - Update type-alias-impl-trait.md - Update README.md --- library/stdarch/crates/intrinsic-test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/crates/intrinsic-test/README.md b/library/stdarch/crates/intrinsic-test/README.md index 260d59fca80f7..bea95f91e9e1c 100644 --- a/library/stdarch/crates/intrinsic-test/README.md +++ b/library/stdarch/crates/intrinsic-test/README.md @@ -7,7 +7,7 @@ USAGE: intrinsic-test [FLAGS] [OPTIONS] FLAGS: - --a32 Run tests for A32 instrinsics instead of A64 + --a32 Run tests for A32 intrinsics instead of A64 --generate-only Regenerate test programs, but don't build or run them -h, --help Prints help information -V, --version Prints version information From 8600192a42ff43cb8d739772829cf4f04fae61ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 4 Jul 2025 13:16:59 +0200 Subject: [PATCH 10/36] Add config files for `rustc-josh-sync` --- library/stdarch/josh-sync.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 library/stdarch/josh-sync.toml diff --git a/library/stdarch/josh-sync.toml b/library/stdarch/josh-sync.toml new file mode 100644 index 0000000000000..ebdb4576287c8 --- /dev/null +++ b/library/stdarch/josh-sync.toml @@ -0,0 +1,3 @@ +org = "rust-lang" +repo = "stdarch" +path = "library/stdarch" From ce73251d44a8c60a77951ce989bda57aafd144cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 4 Jul 2025 13:21:47 +0200 Subject: [PATCH 11/36] Prepare for merging from rust-lang/rust This updates the rust-version file to 1b61d43bdbf875183b1f436302d62ff93f9a6bba. --- library/stdarch/rust-version | 1 + 1 file changed, 1 insertion(+) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index e69de29bb2d1d..56a727c28200f 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -0,0 +1 @@ +1b61d43bdbf875183b1f436302d62ff93f9a6bba From 1bc289da3a90cecf3d288c28a2c8a5d8c9fcd371 Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Sun, 29 Jun 2025 07:06:25 +0000 Subject: [PATCH 12/36] std_detect: RISC-V Linux: Ergonomic querying with `riscv_hwprobe` Originally, we used an array of `riscv_hwprobe` directly and indexed using raw numbers, making correspondence between the index and the query key less obvious. We also frequently used `out[idx].key != -1` to test whether the key is supported by the `riscv_hwprobe` system call (on the Linux kernel version we are testing) but we'd better to integrate with an operation to retrieve the value. This commit improves the ergonomics of feature querying by: 1. Utilizing macros to a. enable indexing by identifier names and b. encapsulate accesses to the `riscv_hwprobe` array to query and 2. New method `riscv_hwprobe::get()` returning `Option`, integrating availability checking and value retrieval. It also removes `has_ima` for now because it's redundant if we only need to test for single base behavior. --- .../std_detect/src/detect/os/linux/riscv.rs | 83 ++++++++++--------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs index e044d5f15412f..db20538af9512 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs @@ -25,6 +25,13 @@ struct riscv_hwprobe { value: u64, } +impl riscv_hwprobe { + // key is overwritten to -1 if not supported by riscv_hwprobe syscall. + pub fn get(&self) -> Option { + (self.key != -1).then_some(self.value) + } +} + #[allow(non_upper_case_globals)] const __NR_riscv_hwprobe: libc::c_long = 258; @@ -155,49 +162,45 @@ pub(crate) fn detect_features() -> cache::Initializer { // Use riscv_hwprobe syscall to query more extensions and // performance-related capabilities. 'hwprobe: { - let mut out = [ - riscv_hwprobe { - key: RISCV_HWPROBE_KEY_BASE_BEHAVIOR, - value: 0, - }, - riscv_hwprobe { - key: RISCV_HWPROBE_KEY_IMA_EXT_0, - value: 0, - }, - riscv_hwprobe { - key: RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF, - value: 0, - }, - riscv_hwprobe { - key: RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF, - value: 0, - }, - riscv_hwprobe { - key: RISCV_HWPROBE_KEY_CPUPERF_0, - value: 0, - }, - ]; - if !_riscv_hwprobe(&mut out) { + macro_rules! init { + { $($name: ident : $key: expr),* $(,)? } => { + #[repr(usize)] + enum Indices { $($name),* } + let mut t = [$(riscv_hwprobe { key: $key, value: 0 }),*]; + macro_rules! data_mut { () => { &mut t } } + macro_rules! query { [$idx: ident] => { t[Indices::$idx as usize].get() } } + } + } + init! { + BaseBehavior: RISCV_HWPROBE_KEY_BASE_BEHAVIOR, + Extensions: RISCV_HWPROBE_KEY_IMA_EXT_0, + MisalignedScalarPerf: RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF, + MisalignedVectorPerf: RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF, + MisalignedScalarPerfFallback: RISCV_HWPROBE_KEY_CPUPERF_0, + }; + if !_riscv_hwprobe(data_mut!()) { break 'hwprobe; } - // Query scalar/vector misaligned behavior. - if out[2].key != -1 { + // Query scalar misaligned behavior. + if let Some(value) = query![MisalignedScalarPerf] { enable_feature( Feature::unaligned_scalar_mem, - out[2].value == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST, + value == RISCV_HWPROBE_MISALIGNED_SCALAR_FAST, ); - } else if out[4].key != -1 { + } else if let Some(value) = query![MisalignedScalarPerfFallback] { // Deprecated method for fallback enable_feature( Feature::unaligned_scalar_mem, - out[4].value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST, + value & RISCV_HWPROBE_MISALIGNED_MASK == RISCV_HWPROBE_MISALIGNED_FAST, ); } - if out[3].key != -1 { + + // Query vector misaligned behavior. + if let Some(value) = query![MisalignedVectorPerf] { enable_feature( Feature::unaligned_vector_mem, - out[3].value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST, + value == RISCV_HWPROBE_MISALIGNED_VECTOR_FAST, ); } @@ -207,22 +210,20 @@ pub(crate) fn detect_features() -> cache::Initializer { // 20240411). // This is a current requirement of // `RISCV_HWPROBE_KEY_IMA_EXT_0`-based tests. - let has_ima = (out[0].key != -1) && (out[0].value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA != 0); - if !has_ima { + if query![BaseBehavior].is_none_or(|value| value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA == 0) { break 'hwprobe; } - has_i |= has_ima; - enable_feature(Feature::zicsr, has_ima); - enable_feature(Feature::zicntr, has_ima); - enable_feature(Feature::zifencei, has_ima); - enable_feature(Feature::m, has_ima); - enable_feature(Feature::a, has_ima); + has_i = true; + enable_feature(Feature::zicsr, true); + enable_feature(Feature::zicntr, true); + enable_feature(Feature::zifencei, true); + enable_feature(Feature::m, true); + enable_feature(Feature::a, true); // Enable features based on `RISCV_HWPROBE_KEY_IMA_EXT_0`. - if out[1].key == -1 { + let Some(ima_ext_0) = query![Extensions] else { break 'hwprobe; - } - let ima_ext_0 = out[1].value; + }; let test = |mask| (ima_ext_0 & mask) != 0; enable_feature(Feature::d, test(RISCV_HWPROBE_IMA_FD)); // F is implied. From fddd05bd7f2a01004f5c21c99f5fcab0f47e3b45 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Sun, 6 Jul 2025 07:15:54 +0000 Subject: [PATCH 13/36] some clippy fixes --- .../stdarch/crates/core_arch/src/aarch64/neon/generated.rs | 5 ++--- library/stdarch/crates/core_arch/src/arm_shared/mod.rs | 6 +++--- .../stdarch/crates/core_arch/src/arm_shared/neon/mod.rs | 2 +- .../stdarch/crates/intrinsic-test/src/common/compare.rs | 2 +- library/stdarch/crates/intrinsic-test/src/common/gen_c.rs | 2 +- .../stdarch/crates/intrinsic-test/src/common/gen_rust.rs | 2 +- .../crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml | 7 +++---- 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 96ed82021b4b2..d6f15fc8a520b 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -7925,7 +7925,7 @@ pub fn vcvth_f16_u64(a: u64) -> f16 { #[unstable(feature = "stdarch_neon_f16", issue = "136306")] pub fn vcvth_n_f16_s16(a: i16) -> f16 { static_assert!(N >= 1 && N <= 16); - vcvth_n_f16_s32::(a as i32) as f16 + vcvth_n_f16_s32::(a as i32) } #[doc = "Fixed-point convert to floating-point"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcvth_n_f16_s32)"] @@ -7972,7 +7972,7 @@ pub fn vcvth_n_f16_s64(a: i64) -> f16 { #[unstable(feature = "stdarch_neon_f16", issue = "136306")] pub fn vcvth_n_f16_u16(a: u16) -> f16 { static_assert!(N >= 1 && N <= 16); - vcvth_n_f16_u32::(a as u32) as f16 + vcvth_n_f16_u32::(a as u32) } #[doc = "Fixed-point convert to floating-point"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcvth_n_f16_u32)"] @@ -24082,7 +24082,6 @@ pub fn vrsqrtes_f32(a: f32) -> f32 { #[doc = "Reciprocal square-root estimate."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrsqrteh_f16)"] #[inline] -#[target_feature(enable = "neon,fp16")] #[cfg_attr(test, assert_instr(frsqrte))] #[target_feature(enable = "neon,fp16")] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/mod.rs index 527b53de99d95..8074648a28a28 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/mod.rs @@ -20,10 +20,10 @@ //! Section 10.1 of ACLE says: //! //! - "In the sequence of Arm architectures { v5, v5TE, v6, v6T2, v7 } each architecture includes -//! its predecessor instruction set." +//! its predecessor's instruction set." //! //! - "In the sequence of Thumb-only architectures { v6-M, v7-M, v7E-M } each architecture includes -//! its predecessor instruction set." +//! its predecessor's instruction set." //! //! From that info and from looking at how LLVM features work (using custom targets) we can identify //! features that are subsets of others: @@ -38,7 +38,7 @@ //! *NOTE*: Section 5.4.7 of ACLE says: //! //! - "__ARM_FEATURE_DSP is defined to 1 if the DSP (v5E) instructions are supported and the -//! intrinsics defined in Saturating intrinsics are available." +//! intrinsics defined in Saturating intrinsics are available." //! //! This does *not* match how LLVM uses the '+dsp' feature; this feature is not set for v5te //! targets so we have to work around this difference. diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs index 0683d48ed3271..60c9daef68c42 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs @@ -777,8 +777,8 @@ pub struct float16x8x2_t(pub float16x8_t, pub float16x8_t); #[repr(C)] #[derive(Copy, Clone, Debug)] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] - pub struct float16x8x3_t(pub float16x8_t, pub float16x8_t, pub float16x8_t); + /// Arm-specific type containing four `float16x8_t` vectors. #[repr(C)] #[derive(Copy, Clone, Debug)] diff --git a/library/stdarch/crates/intrinsic-test/src/common/compare.rs b/library/stdarch/crates/intrinsic-test/src/common/compare.rs index 815ccf89fc695..9e0cbe8cd6abe 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/compare.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/compare.rs @@ -48,7 +48,7 @@ pub fn compare_outputs( return Some(FailureReason::RunRust(intrinsic_name.clone())); } - info!("Comparing intrinsic: {}", intrinsic_name); + info!("Comparing intrinsic: {intrinsic_name}"); let c = std::str::from_utf8(&c.stdout) .unwrap() diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index 84c28cc4bf439..1cfb66c39b90f 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -79,7 +79,7 @@ pub fn compile_c_programs(compiler_commands: &[String]) -> bool { false } } else { - error!("Command failed: {:#?}", output); + error!("Command failed: {output:#?}"); false } }) diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index a2878502ac944..52bccaf905c51 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -120,7 +120,7 @@ path = "{binary}/main.rs""#, false } } else { - error!("Command failed: {:#?}", output); + error!("Command failed: {output:#?}"); false } } diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index f658267b9a19b..f5f44f4456690 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -1252,7 +1252,7 @@ intrinsics: - [i16, f16, 'h', 'i32', 'as i32'] compose: - FnCall: [static_assert!, ['N >= 1 && N <= 16']] - - "vcvt{type[2]}_n_{type[1]}_{type[3]}::(a {type[4]}) as {type[1]}" + - "vcvt{type[2]}_n_{type[1]}_{type[3]}::(a {type[4]})" - name: "vcvt{type[2]}_n_{type[1]}_{type[0]}" @@ -1270,7 +1270,7 @@ intrinsics: - [u16, f16, 'h', u32] compose: - FnCall: [static_assert!, ['N >= 1 && N <= 16']] - - "vcvt{type[2]}_n_{type[1]}_{type[3]}::(a as {type[3]}) as {type[1]}" + - "vcvt{type[2]}_n_{type[1]}_{type[3]}::(a as {type[3]})" - name: "vcvt{type[2]}" @@ -11697,7 +11697,6 @@ intrinsics: arguments: ["a: {type[1]}"] return_type: "{type[1]}" attr: - - *neon-fp16 - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [frsqrte]]}]] - *neon-fp16 - *neon-unstable-f16 @@ -12315,7 +12314,7 @@ intrinsics: compose: - FnCall: - simd_select - - - FnCall: + - - FnCall: - "simd_lt::<{type[4]}_t, int8x8_t>" - - c - FnCall: [transmute, ["{type[3]}"]] From 658b5c8f6950dce7c993ab7580a64b348c278b67 Mon Sep 17 00:00:00 2001 From: sayantn Date: Mon, 7 Jul 2025 07:18:53 +0530 Subject: [PATCH 14/36] Use `simd_funnel_sh{l,r}` and `simd_round_ties_even` to remove uses of LLVM intrinsics --- .../core_arch/src/aarch64/neon/generated.rs | 54 ++------------ .../crates/core_arch/src/powerpc/altivec.rs | 29 ++------ .../crates/core_arch/src/s390x/vector.rs | 41 ++++------ .../crates/core_arch/src/x86/avx512vbmi2.rs | 74 +++++-------------- .../spec/neon/aarch64.spec.yml | 12 +-- 5 files changed, 47 insertions(+), 163 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index d6f15fc8a520b..d5ff9ea554aa1 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -23785,14 +23785,7 @@ pub fn vrndph_f16(a: f16) -> f16 { #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndx_f16(a: float16x4_t) -> float16x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.rint.v4f16" - )] - fn _vrndx_f16(a: float16x4_t) -> float16x4_t; - } - unsafe { _vrndx_f16(a) } + unsafe { simd_round_ties_even(a) } } #[doc = "Floating-point round to integral exact, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndxq_f16)"] @@ -23801,14 +23794,7 @@ pub fn vrndx_f16(a: float16x4_t) -> float16x4_t { #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndxq_f16(a: float16x8_t) -> float16x8_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.rint.v8f16" - )] - fn _vrndxq_f16(a: float16x8_t) -> float16x8_t; - } - unsafe { _vrndxq_f16(a) } + unsafe { simd_round_ties_even(a) } } #[doc = "Floating-point round to integral exact, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndx_f32)"] @@ -23817,14 +23803,7 @@ pub fn vrndxq_f16(a: float16x8_t) -> float16x8_t { #[stable(feature = "neon_intrinsics", since = "1.59.0")] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndx_f32(a: float32x2_t) -> float32x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.rint.v2f32" - )] - fn _vrndx_f32(a: float32x2_t) -> float32x2_t; - } - unsafe { _vrndx_f32(a) } + unsafe { simd_round_ties_even(a) } } #[doc = "Floating-point round to integral exact, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndxq_f32)"] @@ -23833,14 +23812,7 @@ pub fn vrndx_f32(a: float32x2_t) -> float32x2_t { #[stable(feature = "neon_intrinsics", since = "1.59.0")] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndxq_f32(a: float32x4_t) -> float32x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.rint.v4f32" - )] - fn _vrndxq_f32(a: float32x4_t) -> float32x4_t; - } - unsafe { _vrndxq_f32(a) } + unsafe { simd_round_ties_even(a) } } #[doc = "Floating-point round to integral exact, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndx_f64)"] @@ -23849,14 +23821,7 @@ pub fn vrndxq_f32(a: float32x4_t) -> float32x4_t { #[stable(feature = "neon_intrinsics", since = "1.59.0")] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndx_f64(a: float64x1_t) -> float64x1_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.rint.v1f64" - )] - fn _vrndx_f64(a: float64x1_t) -> float64x1_t; - } - unsafe { _vrndx_f64(a) } + unsafe { simd_round_ties_even(a) } } #[doc = "Floating-point round to integral exact, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndxq_f64)"] @@ -23865,14 +23830,7 @@ pub fn vrndx_f64(a: float64x1_t) -> float64x1_t { #[stable(feature = "neon_intrinsics", since = "1.59.0")] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndxq_f64(a: float64x2_t) -> float64x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.rint.v2f64" - )] - fn _vrndxq_f64(a: float64x2_t) -> float64x2_t; - } - unsafe { _vrndxq_f64(a) } + unsafe { simd_round_ties_even(a) } } #[doc = "Floating-point round to integral, using current rounding mode"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndxh_f16)"] diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index 2deeb53c20995..a7bbf35ed8d0b 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -360,25 +360,6 @@ unsafe extern "C" { #[link_name = "llvm.ppc.altivec.vsrv"] fn vsrv(a: vector_unsigned_char, b: vector_unsigned_char) -> vector_unsigned_char; - #[link_name = "llvm.fshl.v16i8"] - fn fshlb( - a: vector_unsigned_char, - b: vector_unsigned_char, - c: vector_unsigned_char, - ) -> vector_unsigned_char; - #[link_name = "llvm.fshl.v8i16"] - fn fshlh( - a: vector_unsigned_short, - b: vector_unsigned_short, - c: vector_unsigned_short, - ) -> vector_unsigned_short; - #[link_name = "llvm.fshl.v4i32"] - fn fshlw( - a: vector_unsigned_int, - b: vector_unsigned_int, - c: vector_unsigned_int, - ) -> vector_unsigned_int; - #[link_name = "llvm.nearbyint.v4f32"] fn vrfin(a: vector_float) -> vector_float; } @@ -3193,19 +3174,19 @@ mod sealed { impl_vec_cntlz! { vec_vcntlzw(vector_unsigned_int) } macro_rules! impl_vrl { - ($fun:ident $intr:ident $ty:ident) => { + ($fun:ident $ty:ident) => { #[inline] #[target_feature(enable = "altivec")] #[cfg_attr(test, assert_instr($fun))] unsafe fn $fun(a: t_t_l!($ty), b: t_t_l!($ty)) -> t_t_l!($ty) { - transmute($intr(transmute(a), transmute(a), transmute(b))) + simd_funnel_shl(a, a, b) } }; } - impl_vrl! { vrlb fshlb u8 } - impl_vrl! { vrlh fshlh u16 } - impl_vrl! { vrlw fshlw u32 } + impl_vrl! { vrlb u8 } + impl_vrl! { vrlh u16 } + impl_vrl! { vrlw u32 } #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub trait VectorRl { diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index 101de7010699d..1cd33c3554bde 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -83,9 +83,6 @@ unsafe extern "unadjusted" { #[link_name = "llvm.nearbyint.v4f32"] fn nearbyint_v4f32(a: vector_float) -> vector_float; #[link_name = "llvm.nearbyint.v2f64"] fn nearbyint_v2f64(a: vector_double) -> vector_double; - #[link_name = "llvm.rint.v4f32"] fn rint_v4f32(a: vector_float) -> vector_float; - #[link_name = "llvm.rint.v2f64"] fn rint_v2f64(a: vector_double) -> vector_double; - #[link_name = "llvm.roundeven.v4f32"] fn roundeven_v4f32(a: vector_float) -> vector_float; #[link_name = "llvm.roundeven.v2f64"] fn roundeven_v2f64(a: vector_double) -> vector_double; @@ -101,11 +98,6 @@ unsafe extern "unadjusted" { #[link_name = "llvm.s390.vsld"] fn vsld(a: i8x16, b: i8x16, c: u32) -> i8x16; #[link_name = "llvm.s390.vsrd"] fn vsrd(a: i8x16, b: i8x16, c: u32) -> i8x16; - #[link_name = "llvm.fshl.v16i8"] fn fshlb(a: vector_unsigned_char, b: vector_unsigned_char, c: vector_unsigned_char) -> vector_unsigned_char; - #[link_name = "llvm.fshl.v8i16"] fn fshlh(a: vector_unsigned_short, b: vector_unsigned_short, c: vector_unsigned_short) -> vector_unsigned_short; - #[link_name = "llvm.fshl.v4i32"] fn fshlf(a: vector_unsigned_int, b: vector_unsigned_int, c: vector_unsigned_int) -> vector_unsigned_int; - #[link_name = "llvm.fshl.v2i64"] fn fshlg(a: vector_unsigned_long_long, b: vector_unsigned_long_long, c: vector_unsigned_long_long) -> vector_unsigned_long_long; - #[link_name = "llvm.s390.verimb"] fn verimb(a: vector_signed_char, b: vector_signed_char, c: vector_signed_char, d: i32) -> vector_signed_char; #[link_name = "llvm.s390.verimh"] fn verimh(a: vector_signed_short, b: vector_signed_short, c: vector_signed_short, d: i32) -> vector_signed_short; #[link_name = "llvm.s390.verimf"] fn verimf(a: vector_signed_int, b: vector_signed_int, c: vector_signed_int, d: i32) -> vector_signed_int; @@ -1197,8 +1189,8 @@ mod sealed { test_impl! { vec_round_f32 (a: vector_float) -> vector_float [roundeven_v4f32, _] } test_impl! { vec_round_f64 (a: vector_double) -> vector_double [roundeven_v2f64, _] } - test_impl! { vec_rint_f32 (a: vector_float) -> vector_float [rint_v4f32, "vector-enhancements-1" vfisb] } - test_impl! { vec_rint_f64 (a: vector_double) -> vector_double [rint_v2f64, vfidb] } + test_impl! { vec_rint_f32 (a: vector_float) -> vector_float [simd_round_ties_even, "vector-enhancements-1" vfisb] } + test_impl! { vec_rint_f64 (a: vector_double) -> vector_double [simd_round_ties_even, vfidb] } #[unstable(feature = "stdarch_s390x", issue = "135681")] pub trait VectorRoundc { @@ -1221,8 +1213,8 @@ mod sealed { impl_vec_trait! { [VectorRound vec_round] vec_round_f32 (vector_float) } impl_vec_trait! { [VectorRound vec_round] vec_round_f64 (vector_double) } - impl_vec_trait! { [VectorRint vec_rint] vec_rint_f32 (vector_float) } - impl_vec_trait! { [VectorRint vec_rint] vec_rint_f64 (vector_double) } + impl_vec_trait! { [VectorRint vec_rint] simd_round_ties_even (vector_float) } + impl_vec_trait! { [VectorRint vec_rint] simd_round_ties_even (vector_double) } #[unstable(feature = "stdarch_s390x", issue = "135681")] pub trait VectorTrunc { @@ -1411,43 +1403,42 @@ mod sealed { } macro_rules! impl_rot { - ($fun:ident $intr:ident $ty:ident) => { + ($fun:ident $ty:ident) => { #[inline] #[target_feature(enable = "vector")] #[cfg_attr(test, assert_instr($fun))] unsafe fn $fun(a: t_t_l!($ty), b: t_t_l!($ty)) -> t_t_l!($ty) { - transmute($intr(transmute(a), transmute(a), transmute(b))) + simd_funnel_shl(a, a, b) } }; } - impl_rot! { verllvb fshlb u8 } - impl_rot! { verllvh fshlh u16 } - impl_rot! { verllvf fshlf u32 } - impl_rot! { verllvg fshlg u64 } + impl_rot! { verllvb u8 } + impl_rot! { verllvh u16 } + impl_rot! { verllvf u32 } + impl_rot! { verllvg u64 } impl_vec_shift! { [VectorRl vec_rl] (verllvb, verllvh, verllvf, verllvg) } macro_rules! test_rot_imm { - ($fun:ident $instr:ident $intr:ident $ty:ident) => { + ($fun:ident $instr:ident $ty:ident) => { #[inline] #[target_feature(enable = "vector")] #[cfg_attr(test, assert_instr($instr))] unsafe fn $fun(a: t_t_l!($ty), bits: core::ffi::c_ulong) -> t_t_l!($ty) { // mod by the number of bits in a's element type to prevent UB let bits = (bits % $ty::BITS as core::ffi::c_ulong) as $ty; - let a = transmute(a); let b = ::splat(bits); - transmute($intr(a, a, transmute(b))) + simd_funnel_shl(a, a, transmute(b)) } }; } - test_rot_imm! { verllvb_imm verllb fshlb u8 } - test_rot_imm! { verllvh_imm verllh fshlh u16 } - test_rot_imm! { verllvf_imm verllf fshlf u32 } - test_rot_imm! { verllvg_imm verllg fshlg u64 } + test_rot_imm! { verllvb_imm verllb u8 } + test_rot_imm! { verllvh_imm verllh u16 } + test_rot_imm! { verllvf_imm verllf u32 } + test_rot_imm! { verllvg_imm verllg u64 } #[unstable(feature = "stdarch_s390x", issue = "135681")] pub trait VectorRli { diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs b/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs index c722f7b370ffe..09a90e29bf088 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs @@ -500,7 +500,7 @@ pub fn _mm_maskz_expand_epi8(k: __mmask16, a: __m128i) -> __m128i { #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvq))] pub fn _mm512_shldv_epi64(a: __m512i, b: __m512i, c: __m512i) -> __m512i { - unsafe { transmute(vpshldvq(a.as_i64x8(), b.as_i64x8(), c.as_i64x8())) } + unsafe { transmute(simd_funnel_shl(a.as_i64x8(), b.as_i64x8(), c.as_i64x8())) } } /// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -539,7 +539,7 @@ pub fn _mm512_maskz_shldv_epi64(k: __mmask8, a: __m512i, b: __m512i, c: __m512i) #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvq))] pub fn _mm256_shldv_epi64(a: __m256i, b: __m256i, c: __m256i) -> __m256i { - unsafe { transmute(vpshldvq256(a.as_i64x4(), b.as_i64x4(), c.as_i64x4())) } + unsafe { transmute(simd_funnel_shl(a.as_i64x4(), b.as_i64x4(), c.as_i64x4())) } } /// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -578,7 +578,7 @@ pub fn _mm256_maskz_shldv_epi64(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvq))] pub fn _mm_shldv_epi64(a: __m128i, b: __m128i, c: __m128i) -> __m128i { - unsafe { transmute(vpshldvq128(a.as_i64x2(), b.as_i64x2(), c.as_i64x2())) } + unsafe { transmute(simd_funnel_shl(a.as_i64x2(), b.as_i64x2(), c.as_i64x2())) } } /// Concatenate packed 64-bit integers in a and b producing an intermediate 128-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -617,7 +617,7 @@ pub fn _mm_maskz_shldv_epi64(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvd))] pub fn _mm512_shldv_epi32(a: __m512i, b: __m512i, c: __m512i) -> __m512i { - unsafe { transmute(vpshldvd(a.as_i32x16(), b.as_i32x16(), c.as_i32x16())) } + unsafe { transmute(simd_funnel_shl(a.as_i32x16(), b.as_i32x16(), c.as_i32x16())) } } /// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -656,7 +656,7 @@ pub fn _mm512_maskz_shldv_epi32(k: __mmask16, a: __m512i, b: __m512i, c: __m512i #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvd))] pub fn _mm256_shldv_epi32(a: __m256i, b: __m256i, c: __m256i) -> __m256i { - unsafe { transmute(vpshldvd256(a.as_i32x8(), b.as_i32x8(), c.as_i32x8())) } + unsafe { transmute(simd_funnel_shl(a.as_i32x8(), b.as_i32x8(), c.as_i32x8())) } } /// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -695,7 +695,7 @@ pub fn _mm256_maskz_shldv_epi32(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvd))] pub fn _mm_shldv_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { - unsafe { transmute(vpshldvd128(a.as_i32x4(), b.as_i32x4(), c.as_i32x4())) } + unsafe { transmute(simd_funnel_shl(a.as_i32x4(), b.as_i32x4(), c.as_i32x4())) } } /// Concatenate packed 32-bit integers in a and b producing an intermediate 64-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -734,7 +734,7 @@ pub fn _mm_maskz_shldv_epi32(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvw))] pub fn _mm512_shldv_epi16(a: __m512i, b: __m512i, c: __m512i) -> __m512i { - unsafe { transmute(vpshldvw(a.as_i16x32(), b.as_i16x32(), c.as_i16x32())) } + unsafe { transmute(simd_funnel_shl(a.as_i16x32(), b.as_i16x32(), c.as_i16x32())) } } /// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -773,7 +773,7 @@ pub fn _mm512_maskz_shldv_epi16(k: __mmask32, a: __m512i, b: __m512i, c: __m512i #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvw))] pub fn _mm256_shldv_epi16(a: __m256i, b: __m256i, c: __m256i) -> __m256i { - unsafe { transmute(vpshldvw256(a.as_i16x16(), b.as_i16x16(), c.as_i16x16())) } + unsafe { transmute(simd_funnel_shl(a.as_i16x16(), b.as_i16x16(), c.as_i16x16())) } } /// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -812,7 +812,7 @@ pub fn _mm256_maskz_shldv_epi16(k: __mmask16, a: __m256i, b: __m256i, c: __m256i #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshldvw))] pub fn _mm_shldv_epi16(a: __m128i, b: __m128i, c: __m128i) -> __m128i { - unsafe { transmute(vpshldvw128(a.as_i16x8(), b.as_i16x8(), c.as_i16x8())) } + unsafe { transmute(simd_funnel_shl(a.as_i16x8(), b.as_i16x8(), c.as_i16x8())) } } /// Concatenate packed 16-bit integers in a and b producing an intermediate 32-bit result. Shift the result left by the amount specified in the corresponding element of c, and store the upper 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -851,7 +851,7 @@ pub fn _mm_maskz_shldv_epi16(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvq))] pub fn _mm512_shrdv_epi64(a: __m512i, b: __m512i, c: __m512i) -> __m512i { - unsafe { transmute(vpshrdvq(b.as_i64x8(), a.as_i64x8(), c.as_i64x8())) } + unsafe { transmute(simd_funnel_shr(b.as_i64x8(), a.as_i64x8(), c.as_i64x8())) } } /// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -890,7 +890,7 @@ pub fn _mm512_maskz_shrdv_epi64(k: __mmask8, a: __m512i, b: __m512i, c: __m512i) #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvq))] pub fn _mm256_shrdv_epi64(a: __m256i, b: __m256i, c: __m256i) -> __m256i { - unsafe { transmute(vpshrdvq256(b.as_i64x4(), a.as_i64x4(), c.as_i64x4())) } + unsafe { transmute(simd_funnel_shr(b.as_i64x4(), a.as_i64x4(), c.as_i64x4())) } } /// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -929,7 +929,7 @@ pub fn _mm256_maskz_shrdv_epi64(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvq))] pub fn _mm_shrdv_epi64(a: __m128i, b: __m128i, c: __m128i) -> __m128i { - unsafe { transmute(vpshrdvq128(b.as_i64x2(), a.as_i64x2(), c.as_i64x2())) } + unsafe { transmute(simd_funnel_shr(b.as_i64x2(), a.as_i64x2(), c.as_i64x2())) } } /// Concatenate packed 64-bit integers in b and a producing an intermediate 128-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 64-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -968,7 +968,7 @@ pub fn _mm_maskz_shrdv_epi64(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvd))] pub fn _mm512_shrdv_epi32(a: __m512i, b: __m512i, c: __m512i) -> __m512i { - unsafe { transmute(vpshrdvd(b.as_i32x16(), a.as_i32x16(), c.as_i32x16())) } + unsafe { transmute(simd_funnel_shr(b.as_i32x16(), a.as_i32x16(), c.as_i32x16())) } } /// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -1007,7 +1007,7 @@ pub fn _mm512_maskz_shrdv_epi32(k: __mmask16, a: __m512i, b: __m512i, c: __m512i #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvd))] pub fn _mm256_shrdv_epi32(a: __m256i, b: __m256i, c: __m256i) -> __m256i { - unsafe { transmute(vpshrdvd256(b.as_i32x8(), a.as_i32x8(), c.as_i32x8())) } + unsafe { transmute(simd_funnel_shr(b.as_i32x8(), a.as_i32x8(), c.as_i32x8())) } } /// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -1046,7 +1046,7 @@ pub fn _mm256_maskz_shrdv_epi32(k: __mmask8, a: __m256i, b: __m256i, c: __m256i) #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvd))] pub fn _mm_shrdv_epi32(a: __m128i, b: __m128i, c: __m128i) -> __m128i { - unsafe { transmute(vpshrdvd128(b.as_i32x4(), a.as_i32x4(), c.as_i32x4())) } + unsafe { transmute(simd_funnel_shr(b.as_i32x4(), a.as_i32x4(), c.as_i32x4())) } } /// Concatenate packed 32-bit integers in b and a producing an intermediate 64-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 32-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -1085,7 +1085,7 @@ pub fn _mm_maskz_shrdv_epi32(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) -> #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvw))] pub fn _mm512_shrdv_epi16(a: __m512i, b: __m512i, c: __m512i) -> __m512i { - unsafe { transmute(vpshrdvw(b.as_i16x32(), a.as_i16x32(), c.as_i16x32())) } + unsafe { transmute(simd_funnel_shr(b.as_i16x32(), a.as_i16x32(), c.as_i16x32())) } } /// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -1124,7 +1124,7 @@ pub fn _mm512_maskz_shrdv_epi16(k: __mmask32, a: __m512i, b: __m512i, c: __m512i #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvw))] pub fn _mm256_shrdv_epi16(a: __m256i, b: __m256i, c: __m256i) -> __m256i { - unsafe { transmute(vpshrdvw256(b.as_i16x16(), a.as_i16x16(), c.as_i16x16())) } + unsafe { transmute(simd_funnel_shr(b.as_i16x16(), a.as_i16x16(), c.as_i16x16())) } } /// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -1163,7 +1163,7 @@ pub fn _mm256_maskz_shrdv_epi16(k: __mmask16, a: __m256i, b: __m256i, c: __m256i #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpshrdvw))] pub fn _mm_shrdv_epi16(a: __m128i, b: __m128i, c: __m128i) -> __m128i { - unsafe { transmute(vpshrdvw128(b.as_i16x8(), a.as_i16x8(), c.as_i16x8())) } + unsafe { transmute(simd_funnel_shr(b.as_i16x8(), a.as_i16x8(), c.as_i16x8())) } } /// Concatenate packed 16-bit integers in b and a producing an intermediate 32-bit result. Shift the result right by the amount specified in the corresponding element of c, and store the lower 16-bits in dst using writemask k (elements are copied from a when the corresponding mask bit is not set). @@ -2138,44 +2138,6 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.mask.expand.b.128"] fn vpexpandb128(a: i8x16, src: i8x16, mask: u16) -> i8x16; - #[link_name = "llvm.fshl.v8i64"] - fn vpshldvq(a: i64x8, b: i64x8, c: i64x8) -> i64x8; - #[link_name = "llvm.fshl.v4i64"] - fn vpshldvq256(a: i64x4, b: i64x4, c: i64x4) -> i64x4; - #[link_name = "llvm.fshl.v2i64"] - fn vpshldvq128(a: i64x2, b: i64x2, c: i64x2) -> i64x2; - #[link_name = "llvm.fshl.v16i32"] - fn vpshldvd(a: i32x16, b: i32x16, c: i32x16) -> i32x16; - #[link_name = "llvm.fshl.v8i32"] - fn vpshldvd256(a: i32x8, b: i32x8, c: i32x8) -> i32x8; - #[link_name = "llvm.fshl.v4i32"] - fn vpshldvd128(a: i32x4, b: i32x4, c: i32x4) -> i32x4; - #[link_name = "llvm.fshl.v32i16"] - fn vpshldvw(a: i16x32, b: i16x32, c: i16x32) -> i16x32; - #[link_name = "llvm.fshl.v16i16"] - fn vpshldvw256(a: i16x16, b: i16x16, c: i16x16) -> i16x16; - #[link_name = "llvm.fshl.v8i16"] - fn vpshldvw128(a: i16x8, b: i16x8, c: i16x8) -> i16x8; - - #[link_name = "llvm.fshr.v8i64"] - fn vpshrdvq(a: i64x8, b: i64x8, c: i64x8) -> i64x8; - #[link_name = "llvm.fshr.v4i64"] - fn vpshrdvq256(a: i64x4, b: i64x4, c: i64x4) -> i64x4; - #[link_name = "llvm.fshr.v2i64"] - fn vpshrdvq128(a: i64x2, b: i64x2, c: i64x2) -> i64x2; - #[link_name = "llvm.fshr.v16i32"] - fn vpshrdvd(a: i32x16, b: i32x16, c: i32x16) -> i32x16; - #[link_name = "llvm.fshr.v8i32"] - fn vpshrdvd256(a: i32x8, b: i32x8, c: i32x8) -> i32x8; - #[link_name = "llvm.fshr.v4i32"] - fn vpshrdvd128(a: i32x4, b: i32x4, c: i32x4) -> i32x4; - #[link_name = "llvm.fshr.v32i16"] - fn vpshrdvw(a: i16x32, b: i16x32, c: i16x32) -> i16x32; - #[link_name = "llvm.fshr.v16i16"] - fn vpshrdvw256(a: i16x16, b: i16x16, c: i16x16) -> i16x16; - #[link_name = "llvm.fshr.v8i16"] - fn vpshrdvw128(a: i16x8, b: i16x8, c: i16x8) -> i16x8; - #[link_name = "llvm.x86.avx512.mask.expand.load.b.128"] fn expandloadb_128(mem_addr: *const i8, a: i8x16, mask: u16) -> i8x16; #[link_name = "llvm.x86.avx512.mask.expand.load.w.128"] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index f5f44f4456690..b4ddd46889940 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -2976,11 +2976,7 @@ intrinsics: - float64x1_t - float64x2_t compose: - - LLVMLink: - name: "llvm.rint.{neon_type}" - links: - - link: "llvm.rint.{neon_type}" - arch: aarch64,arm64ec + - FnCall: [simd_round_ties_even, [a]] - name: "vrndx{neon_type.no}" @@ -2996,11 +2992,7 @@ intrinsics: - float16x4_t - float16x8_t compose: - - LLVMLink: - name: "llvm.rint.{neon_type}" - links: - - link: "llvm.rint.{neon_type}" - arch: aarch64,arm64ec + - FnCall: [simd_round_ties_even, [a]] - name: "vrndx{type[1]}{type[0]}" From a95bd00e8db650d04b54d740a553c9cb80d4e165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 8 Jul 2025 08:55:45 +0200 Subject: [PATCH 15/36] Remove custom josh-sync scripts --- library/stdarch/josh-sync/Cargo.lock | 437 -------------------------- library/stdarch/josh-sync/Cargo.toml | 11 - library/stdarch/josh-sync/README.md | 4 - library/stdarch/josh-sync/src/main.rs | 41 --- library/stdarch/josh-sync/src/sync.rs | 275 ---------------- 5 files changed, 768 deletions(-) delete mode 100644 library/stdarch/josh-sync/Cargo.lock delete mode 100644 library/stdarch/josh-sync/Cargo.toml delete mode 100644 library/stdarch/josh-sync/README.md delete mode 100644 library/stdarch/josh-sync/src/main.rs delete mode 100644 library/stdarch/josh-sync/src/sync.rs diff --git a/library/stdarch/josh-sync/Cargo.lock b/library/stdarch/josh-sync/Cargo.lock deleted file mode 100644 index f3d1fd0d1fe1f..0000000000000 --- a/library/stdarch/josh-sync/Cargo.lock +++ /dev/null @@ -1,437 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "anstream" -version = "0.6.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" - -[[package]] -name = "anstyle-parse" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.59.0", -] - -[[package]] -name = "anyhow" -version = "1.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" - -[[package]] -name = "bitflags" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "cfg-if" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "clap" -version = "4.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" - -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - -[[package]] -name = "directories" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "josh-sync" -version = "0.0.0" -dependencies = [ - "anyhow", - "clap", - "directories", - "xshell", -] - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "libredox" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" -dependencies = [ - "bitflags", - "libc", -] - -[[package]] -name = "once_cell_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "xshell" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d" -dependencies = [ - "xshell-macros", -] - -[[package]] -name = "xshell-macros" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547" diff --git a/library/stdarch/josh-sync/Cargo.toml b/library/stdarch/josh-sync/Cargo.toml deleted file mode 100644 index b4dbde9e875e0..0000000000000 --- a/library/stdarch/josh-sync/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "josh-sync" -edition = "2024" - -[dependencies] -anyhow = "1.0.95" -clap = { version = "4.5.21", features = ["derive"] } -directories = "5" -xshell = "0.2.6" - -[workspace] diff --git a/library/stdarch/josh-sync/README.md b/library/stdarch/josh-sync/README.md deleted file mode 100644 index a3dd876e8b87b..0000000000000 --- a/library/stdarch/josh-sync/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Git josh sync -This utility serves for syncing the josh git subtree to and from the rust-lang/rust repository. - -See CLI help for usage. diff --git a/library/stdarch/josh-sync/src/main.rs b/library/stdarch/josh-sync/src/main.rs deleted file mode 100644 index 2ec061a43b79c..0000000000000 --- a/library/stdarch/josh-sync/src/main.rs +++ /dev/null @@ -1,41 +0,0 @@ -use clap::Parser; - -use crate::sync::{GitSync, RustcPullError}; - -mod sync; - -#[derive(clap::Parser)] -enum Args { - /// Pull changes from the main `rustc` repository. - /// This creates new commits that should be then merged into `stdarch`. - RustcPull, - /// Push changes from `stdarch` to the given `branch` of a `rustc` fork under the given - /// GitHub `username`. - /// The pushed branch should then be merged into the `rustc` repository. - RustcPush { branch: String, github_username: String }, -} - -fn main() -> anyhow::Result<()> { - let args = Args::parse(); - let sync = GitSync::from_current_dir()?; - match args { - Args::RustcPull => { - if let Err(error) = sync.rustc_pull(None) { - match error { - RustcPullError::NothingToPull => { - eprintln!("Nothing to pull"); - std::process::exit(2); - } - RustcPullError::PullFailed(error) => { - eprintln!("Pull failure: {error:?}"); - std::process::exit(1); - } - } - } - } - Args::RustcPush { github_username, branch } => { - sync.rustc_push(github_username, branch)?; - } - } - Ok(()) -} diff --git a/library/stdarch/josh-sync/src/sync.rs b/library/stdarch/josh-sync/src/sync.rs deleted file mode 100644 index f868a7b48ea31..0000000000000 --- a/library/stdarch/josh-sync/src/sync.rs +++ /dev/null @@ -1,275 +0,0 @@ -use std::io::Write; -use std::ops::Not; -use std::path::PathBuf; -use std::time::Duration; -use std::{env, net, process}; - -use anyhow::{Context, anyhow, bail}; -use xshell::{Shell, cmd}; - -/// Used for rustc syncs. -const JOSH_FILTER: &str = ":/library/stdarch"; -const JOSH_PORT: u16 = 42042; -const UPSTREAM_REPO: &str = "rust-lang/rust"; - -pub enum RustcPullError { - /// No changes are available to be pulled. - NothingToPull, - /// A rustc-pull has failed, probably a git operation error has occurred. - PullFailed(anyhow::Error), -} - -impl From for RustcPullError -where - E: Into, -{ - fn from(error: E) -> Self { - Self::PullFailed(error.into()) - } -} - -pub struct GitSync { - dir: PathBuf, -} - -/// This code was adapted from the miri repository -/// (https://github.com/rust-lang/miri/blob/6a68a79f38064c3bc30617cca4bdbfb2c336b140/miri-script/src/commands.rs#L236). -impl GitSync { - pub fn from_current_dir() -> anyhow::Result { - Ok(Self { dir: std::env::current_dir()? }) - } - - pub fn rustc_pull(&self, commit: Option) -> Result<(), RustcPullError> { - let sh = Shell::new()?; - sh.change_dir(&self.dir); - let commit = commit.map(Ok).unwrap_or_else(|| { - let rust_repo_head = - cmd!(sh, "git ls-remote https://github.com/{UPSTREAM_REPO}/ HEAD").read()?; - rust_repo_head - .split_whitespace() - .next() - .map(|front| front.trim().to_owned()) - .ok_or_else(|| anyhow!("Could not obtain Rust repo HEAD from remote.")) - })?; - // Make sure the repo is clean. - if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() { - return Err(anyhow::anyhow!( - "working directory must be clean before performing rustc pull" - ) - .into()); - } - // Make sure josh is running. - let josh = Self::start_josh()?; - let josh_url = - format!("http://localhost:{JOSH_PORT}/{UPSTREAM_REPO}.git@{commit}{JOSH_FILTER}.git"); - - let previous_base_commit = sh.read_file("rust-version")?.trim().to_string(); - if previous_base_commit == commit { - return Err(RustcPullError::NothingToPull); - } - - // Update rust-version file. As a separate commit, since making it part of - // the merge has confused the heck out of josh in the past. - // We pass `--no-verify` to avoid running git hooks. - // We do this before the merge so that if there are merge conflicts, we have - // the right rust-version file while resolving them. - sh.write_file("rust-version", format!("{commit}\n"))?; - const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rustc"; - cmd!(sh, "git commit rust-version --no-verify -m {PREPARING_COMMIT_MESSAGE}") - .run() - .context("FAILED to commit rust-version file, something went wrong")?; - - // Fetch given rustc commit. - cmd!(sh, "git fetch {josh_url}") - .run() - .inspect_err(|_| { - // Try to un-do the previous `git commit`, to leave the repo in the state we found it. - cmd!(sh, "git reset --hard HEAD^") - .run() - .expect("FAILED to clean up again after failed `git fetch`, sorry for that"); - }) - .context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?; - - // This should not add any new root commits. So count those before and after merging. - let num_roots = || -> anyhow::Result { - Ok(cmd!(sh, "git rev-list HEAD --max-parents=0 --count") - .read() - .context("failed to determine the number of root commits")? - .parse::()?) - }; - let num_roots_before = num_roots()?; - - let sha = - cmd!(sh, "git rev-parse HEAD").output().context("FAILED to get current commit")?.stdout; - - // Merge the fetched commit. - const MERGE_COMMIT_MESSAGE: &str = "Merge from rustc"; - cmd!(sh, "git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}") - .run() - .context("FAILED to merge new commits, something went wrong")?; - - let current_sha = - cmd!(sh, "git rev-parse HEAD").output().context("FAILED to get current commit")?.stdout; - if current_sha == sha { - cmd!(sh, "git reset --hard HEAD^") - .run() - .expect("FAILED to clean up after creating the preparation commit"); - eprintln!( - "No merge was performed, no changes to pull were found. Rolled back the preparation commit." - ); - return Err(RustcPullError::NothingToPull); - } - - // Check that the number of roots did not increase. - if num_roots()? != num_roots_before { - return Err(anyhow::anyhow!( - "Josh created a new root commit. This is probably not the history you want." - ) - .into()); - } - - drop(josh); - Ok(()) - } - - pub fn rustc_push(&self, github_user: String, branch: String) -> anyhow::Result<()> { - let sh = Shell::new()?; - sh.change_dir(&self.dir); - let base = sh.read_file("rust-version")?.trim().to_owned(); - // Make sure the repo is clean. - if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() { - bail!("working directory must be clean before running `rustc-push`"); - } - // Make sure josh is running. - let josh = Self::start_josh()?; - let josh_url = - format!("http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git"); - - // Find a repo we can do our preparation in. - if let Ok(rustc_git) = env::var("RUSTC_GIT") { - // If rustc_git is `Some`, we'll use an existing fork for the branch updates. - sh.change_dir(rustc_git); - } else { - // Otherwise, do this in the local repo. - println!( - "This will pull a copy of the rust-lang/rust history into this checkout, growing it by about 1GB." - ); - print!( - "To avoid that, abort now and set the `RUSTC_GIT` environment variable to an existing rustc checkout. Proceed? [y/N] " - ); - std::io::stdout().flush()?; - let mut answer = String::new(); - std::io::stdin().read_line(&mut answer)?; - if answer.trim().to_lowercase() != "y" { - std::process::exit(1); - } - }; - // Prepare the branch. Pushing works much better if we use as base exactly - // the commit that we pulled from last time, so we use the `rust-version` - // file to find out which commit that would be. - println!("Preparing {github_user}/rust (base: {base})..."); - if cmd!(sh, "git fetch https://github.com/{github_user}/rust {branch}") - .ignore_stderr() - .read() - .is_ok() - { - println!( - "The branch '{branch}' seems to already exist in 'https://github.com/{github_user}/rust'. Please delete it and try again." - ); - std::process::exit(1); - } - cmd!(sh, "git fetch https://github.com/{UPSTREAM_REPO} {base}").run()?; - cmd!(sh, "git push https://github.com/{github_user}/rust {base}:refs/heads/{branch}") - .ignore_stdout() - .ignore_stderr() // silence the "create GitHub PR" message - .run()?; - println!(); - - // Do the actual push. - sh.change_dir(&self.dir); - println!("Pushing changes..."); - cmd!(sh, "git push {josh_url} HEAD:{branch}").run()?; - println!(); - - // Do a round-trip check to make sure the push worked as expected. - cmd!(sh, "git fetch {josh_url} {branch}").ignore_stderr().read()?; - let head = cmd!(sh, "git rev-parse HEAD").read()?; - let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?; - if head != fetch_head { - bail!( - "Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\ - Expected {head}, got {fetch_head}." - ); - } - println!( - "Confirmed that the push round-trips back to stdarch properly. Please create a rustc PR:" - ); - println!( - // Open PR with `subtree update` title to silence the `no-merges` triagebot check - " https://github.com/{UPSTREAM_REPO}/compare/{github_user}:{branch}?quick_pull=1&title=stdarch+subtree+update&body=r?+@ghost" - ); - - drop(josh); - Ok(()) - } - - fn start_josh() -> anyhow::Result { - // Determine cache directory. - let local_dir = { - let user_dirs = - directories::ProjectDirs::from("org", "rust-lang", "stdarch-josh").unwrap(); - user_dirs.cache_dir().to_owned() - }; - - // Start josh, silencing its output. - let mut cmd = process::Command::new("josh-proxy"); - cmd.arg("--local").arg(local_dir); - cmd.arg("--remote").arg("https://github.com"); - cmd.arg("--port").arg(JOSH_PORT.to_string()); - cmd.arg("--no-background"); - cmd.stdout(process::Stdio::null()); - cmd.stderr(process::Stdio::null()); - let josh = cmd.spawn().context("failed to start josh-proxy, make sure it is installed")?; - - // Create a wrapper that stops it on drop. - struct Josh(process::Child); - impl Drop for Josh { - fn drop(&mut self) { - #[cfg(unix)] - { - // Try to gracefully shut it down. - process::Command::new("kill") - .args(["-s", "INT", &self.0.id().to_string()]) - .output() - .expect("failed to SIGINT josh-proxy"); - // Sadly there is no "wait with timeout"... so we just give it some time to finish. - std::thread::sleep(Duration::from_millis(100)); - // Now hopefully it is gone. - if self.0.try_wait().expect("failed to wait for josh-proxy").is_some() { - return; - } - } - // If that didn't work (or we're not on Unix), kill it hard. - eprintln!( - "I have to kill josh-proxy the hard way, let's hope this does not break anything." - ); - self.0.kill().expect("failed to SIGKILL josh-proxy"); - } - } - - // Wait until the port is open. We try every 10ms until 1s passed. - for _ in 0..100 { - // This will generally fail immediately when the port is still closed. - let josh_ready = net::TcpStream::connect_timeout( - &net::SocketAddr::from(([127, 0, 0, 1], JOSH_PORT)), - Duration::from_millis(1), - ); - if josh_ready.is_ok() { - return Ok(Josh(josh)); - } - // Not ready yet. - std::thread::sleep(Duration::from_millis(10)); - } - bail!("Even after waiting for 1s, josh-proxy is still not available.") - } -} From 07d5fbb751bafe0e75e6c14951a658a9477c8a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 8 Jul 2025 08:55:55 +0200 Subject: [PATCH 16/36] Update README with link to `josh-sync` --- library/stdarch/README.md | 47 ++------------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/library/stdarch/README.md b/library/stdarch/README.md index 22d8e2357c216..9a35f4cd6ff58 100644 --- a/library/stdarch/README.md +++ b/library/stdarch/README.md @@ -19,49 +19,6 @@ The `std::simd` component now lives in the ## Synchronizing josh subtree with rustc -This repository is linked to `rust-lang/rust` as a [josh](https://josh-project.github.io/josh/intro.html) subtree. You can use the following commands to synchronize the subtree in both directions. +This repository is linked to `rust-lang/rust` as a [josh](https://josh-project.github.io/josh/intro.html) subtree. You can use the [rustc-josh-sync](https://github.com/rust-lang/josh-sync) tool to perform synchronization. -You'll need to install `josh-proxy` locally via - -``` -cargo install josh-proxy --git https://github.com/josh-project/josh --tag r24.10.04 -``` -Older versions of `josh-proxy` may not round trip commits losslessly so it is important to install this exact version. - -### Pull changes from `rust-lang/rust` into this repository - -1) Checkout a new branch that will be used to create a PR into `rust-lang/stdarch` -2) Run the pull command - ``` - cargo run --manifest-path josh-sync/Cargo.toml rustc-pull - ``` -3) Push the branch to your fork and create a PR into `stdarch` - -### Push changes from this repository into `rust-lang/rust` - -NOTE: If you use Git protocol to push to your fork of `rust-lang/rust`, -ensure that you have this entry in your Git config, -else the 2 steps that follow would prompt for a username and password: - -``` -[url "git@github.com:"] -insteadOf = "https://github.com/" -``` - -1) Run the push command to create a branch named `` in a `rustc` fork under the `` account - ``` - cargo run --manifest-path josh-sync/Cargo.toml rustc-push - ``` -2) Create a PR from `` into `rust-lang/rust` - -#### Minimal git config - -For simplicity (ease of implementation purposes), the josh-sync script simply calls out to system git. This means that the git invocation may be influenced by global (or local) git configuration. - -You may observe "Nothing to pull" even if you *know* rustc-pull has something to pull if your global git config sets `fetch.prunetags = true` (and possibly other configurations may cause unexpected outcomes). - -To minimize the likelihood of this happening, you may wish to keep a separate *minimal* git config that *only* has `[user]` entries from global git config, then repoint system git to use the minimal git config instead. E.g. - -``` -GIT_CONFIG_GLOBAL=/path/to/minimal/gitconfig GIT_CONFIG_SYSTEM='' cargo run --manifest-path josh-sync/Cargo.toml -- rustc-pull -``` +You can find a guide on how to perform the synchronization [here](https://rustc-dev-guide.rust-lang.org/external-repos.html#synchronizing-a-josh-subtree). From 82126a6ebaf18cf4d29e820a823fa85b1df832be Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 8 Jul 2025 08:36:41 +0200 Subject: [PATCH 17/36] fix whitespace in `aarch64.spec.yml` --- .../spec/neon/aarch64.spec.yml | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index b4ddd46889940..ca00e3cc83f4c 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -5383,7 +5383,7 @@ intrinsics: attr: - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [fmulx, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['2']] - - *neon-fp16 + - *neon-fp16 - *neon-unstable-f16 static_defs: ["const LANE: i32"] safety: safe @@ -5436,7 +5436,7 @@ intrinsics: attr: - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [fmulx, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['2']] - - *neon-fp16 + - *neon-fp16 - *neon-unstable-f16 static_defs: ["const LANE: i32"] safety: safe @@ -5460,7 +5460,7 @@ intrinsics: return_type: "{neon_type[0]}" attr: - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [fmulx]]}]] - - *neon-fp16 + - *neon-fp16 - *neon-unstable-f16 safety: safe types: @@ -5544,7 +5544,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[0]}", "c: {type[1]}"] return_type: "{neon_type[0]}" attr: - - *neon-fp16 + - *neon-fp16 - *neon-unstable-f16 assert_instr: [fmla] safety: safe @@ -12095,7 +12095,7 @@ intrinsics: - [uint8x8_t, 'uint8x8_t', 'b'] - [poly8x8_t, 'uint8x8_t', 'b'] compose: - - FnCall: + - FnCall: - 'vqtbl1{neon_type[0].no}' - - FnCall: - 'vcombine{neon_type[0].no}' @@ -12165,7 +12165,7 @@ intrinsics: - '{type[2]}_t' - - FnCall: ['vcombine{neon_type[1].no}', ['a.0', 'a.1']] - FnCall: ['vcombine{neon_type[1].no}', ['a.2', 'unsafe {{ crate::mem::zeroed() }}']] - - FnCall: + - FnCall: - transmute - - FnCall: - vqtbl2 @@ -12184,7 +12184,7 @@ intrinsics: types: - [uint8x8x3_t, 'uint8x8_t', 'uint8x16x2', 'uint8x8_t'] - [poly8x8x3_t, 'uint8x8_t', 'poly8x16x2', 'poly8x8_t'] - big_endian_inverse: true + big_endian_inverse: true compose: - Let: - x @@ -12192,7 +12192,7 @@ intrinsics: - '{type[2]}_t' - - FnCall: ['vcombine{neon_type[3].no}', ['a.0', 'a.1']] - FnCall: ['vcombine{neon_type[3].no}', ['a.2', 'unsafe {{ crate::mem::zeroed() }}']] - - FnCall: + - FnCall: - transmute - - FnCall: - vqtbl2 @@ -12290,7 +12290,7 @@ intrinsics: - FnCall: [transmute, [b]] - c - Identifier: [x, Symbol] - + - name: "vtbx1{neon_type[0].no}" doc: "Extended table look-up" arguments: ["a: {neon_type[0]}", "b: {neon_type[0]}", "c: {neon_type[1]}"] @@ -12312,7 +12312,7 @@ intrinsics: - FnCall: [transmute, ["{type[3]}"]] - FnCall: - transmute - - - FnCall: + - - FnCall: - "vqtbx1" - - "transmute(a)" - FnCall: @@ -12466,7 +12466,7 @@ intrinsics: - x - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[2]}' - - FnCall: [transmute, ['a']] - b @@ -12502,7 +12502,7 @@ intrinsics: compose: - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[2]}' - - FnCall: [transmute, ['a.0']] - FnCall: [transmute, ['a.1']] @@ -12538,7 +12538,7 @@ intrinsics: compose: - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[3]}' - - FnCall: [transmute, [a]] - FnCall: [transmute, ['b.0']] @@ -12575,7 +12575,7 @@ intrinsics: compose: - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[3]}' - - FnCall: [transmute, ['a.0']] - FnCall: [transmute, ['a.1']] @@ -12612,7 +12612,7 @@ intrinsics: compose: - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[3]}' - - FnCall: [transmute, [a]] - FnCall: [transmute, ['b.0']] @@ -12650,7 +12650,7 @@ intrinsics: compose: - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[2]}' - - FnCall: [transmute, ['a.0']] - FnCall: [transmute, ['a.1']] @@ -12688,7 +12688,7 @@ intrinsics: compose: - FnCall: - transmute - - - FnCall: + - - FnCall: - '{type[3]}' - - FnCall: [transmute, [a]] - FnCall: [transmute, ['b.0']] @@ -13195,7 +13195,7 @@ intrinsics: assert_instr: [addp] safety: safe types: - - [int32x2_t, i32] + - [int32x2_t, i32] compose: - LLVMLink: name: "vaddv{neon_type[0].no}" @@ -13250,7 +13250,7 @@ intrinsics: assert_instr: [addp] safety: safe types: - - [uint32x2_t, u32, i32] + - [uint32x2_t, u32, i32] compose: - LLVMLink: name: "vaddv{neon_type[0].no}" @@ -13326,7 +13326,7 @@ intrinsics: types: - [int8x8_t, i8, 'smaxv'] - [int16x4_t, i16, 'smaxv'] - - [int32x2_t, i32, 'smaxp'] + - [int32x2_t, i32, 'smaxp'] - [int8x16_t, i8, 'smaxv'] - [int16x8_t, i16, 'smaxv'] - [int32x4_t, i32, 'smaxv'] @@ -13348,7 +13348,7 @@ intrinsics: types: - [uint8x8_t, u8, 'umaxv'] - [uint16x4_t, u16, 'umaxv'] - - [uint32x2_t, u32, 'umaxp'] + - [uint32x2_t, u32, 'umaxp'] - [uint8x16_t, u8, 'umaxv'] - [uint16x8_t, u16, 'umaxv'] - [uint32x4_t, u32, 'umaxv'] @@ -13370,7 +13370,7 @@ intrinsics: types: - [float32x2_t, f32, 'fmaxp'] - [float32x4_t, f32, 'fmaxv'] - - [float64x2_t, f64, 'fmaxp'] + - [float64x2_t, f64, 'fmaxp'] compose: - LLVMLink: name: "vmaxv{neon_type[0].no}" @@ -13389,7 +13389,7 @@ intrinsics: types: - [int8x8_t, i8, 'sminv'] - [int16x4_t, i16, 'sminv'] - - [int32x2_t, i32, 'sminp'] + - [int32x2_t, i32, 'sminp'] - [int8x16_t, i8, 'sminv'] - [int16x8_t, i16, 'sminv'] - [int32x4_t, i32, 'sminv'] @@ -13411,7 +13411,7 @@ intrinsics: types: - [uint8x8_t, u8, 'uminv'] - [uint16x4_t, u16, 'uminv'] - - [uint32x2_t, u32, 'uminp'] + - [uint32x2_t, u32, 'uminp'] - [uint8x16_t, u8, 'uminv'] - [uint16x8_t, u16, 'uminv'] - [uint32x4_t, u32, 'uminv'] @@ -13433,7 +13433,7 @@ intrinsics: types: - [float32x2_t, f32, 'fminp'] - [float32x4_t, f32, 'fminv'] - - [float64x2_t, f64, 'fminp'] + - [float64x2_t, f64, 'fminp'] compose: - LLVMLink: name: "vminv{neon_type[0].no}" @@ -13489,7 +13489,7 @@ intrinsics: safety: safe types: - float32x4_t - - float64x2_t + - float64x2_t compose: - LLVMLink: name: "vpmin{neon_type.no}" @@ -13545,7 +13545,7 @@ intrinsics: safety: safe types: - float32x4_t - - float64x2_t + - float64x2_t compose: - LLVMLink: name: "vpmax{neon_type.no}" From 323c646ec33f93c6bffe2a0f90249aeee35bc0de Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 8 Jul 2025 08:41:09 +0200 Subject: [PATCH 18/36] remote intermediate assignment --- .../core_arch/src/aarch64/neon/generated.rs | 40 ++++--------------- .../spec/neon/aarch64.spec.yml | 34 +++++++--------- 2 files changed, 23 insertions(+), 51 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index d5ff9ea554aa1..c23dd1c8a109a 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -19495,10 +19495,7 @@ pub fn vqtbl1q_s8(a: int8x16_t, b: uint8x16_t) -> int8x16_t { #[cfg_attr(test, assert_instr(tbl))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbl1_u8(a: uint8x16_t, b: uint8x8_t) -> uint8x8_t { - unsafe { - let x = transmute(vqtbl1(transmute(a), b)); - x - } + unsafe { transmute(vqtbl1(transmute(a), b)) } } #[doc = "Table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbl1q_u8)"] @@ -19507,10 +19504,7 @@ pub fn vqtbl1_u8(a: uint8x16_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(test, assert_instr(tbl))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbl1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { - unsafe { - let x = transmute(vqtbl1q(transmute(a), b)); - x - } + unsafe { transmute(vqtbl1q(transmute(a), b)) } } #[doc = "Table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbl1_p8)"] @@ -19519,10 +19513,7 @@ pub fn vqtbl1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(test, assert_instr(tbl))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbl1_p8(a: poly8x16_t, b: uint8x8_t) -> poly8x8_t { - unsafe { - let x = transmute(vqtbl1(transmute(a), b)); - x - } + unsafe { transmute(vqtbl1(transmute(a), b)) } } #[doc = "Table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbl1q_p8)"] @@ -19531,10 +19522,7 @@ pub fn vqtbl1_p8(a: poly8x16_t, b: uint8x8_t) -> poly8x8_t { #[cfg_attr(test, assert_instr(tbl))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbl1q_p8(a: poly8x16_t, b: uint8x16_t) -> poly8x16_t { - unsafe { - let x = transmute(vqtbl1q(transmute(a), b)); - x - } + unsafe { transmute(vqtbl1q(transmute(a), b)) } } #[doc = "Table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbl2)"] @@ -20397,10 +20385,7 @@ pub fn vqtbx1q_s8(a: int8x16_t, b: int8x16_t, c: uint8x16_t) -> int8x16_t { #[cfg_attr(test, assert_instr(tbx))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbx1_u8(a: uint8x8_t, b: uint8x16_t, c: uint8x8_t) -> uint8x8_t { - unsafe { - let x = transmute(vqtbx1(transmute(a), transmute(b), c)); - x - } + unsafe { transmute(vqtbx1(transmute(a), transmute(b), c)) } } #[doc = "Extended table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx1q_u8)"] @@ -20409,10 +20394,7 @@ pub fn vqtbx1_u8(a: uint8x8_t, b: uint8x16_t, c: uint8x8_t) -> uint8x8_t { #[cfg_attr(test, assert_instr(tbx))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbx1q_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { - unsafe { - let x = transmute(vqtbx1q(transmute(a), transmute(b), c)); - x - } + unsafe { transmute(vqtbx1q(transmute(a), transmute(b), c)) } } #[doc = "Extended table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx1_p8)"] @@ -20421,10 +20403,7 @@ pub fn vqtbx1q_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { #[cfg_attr(test, assert_instr(tbx))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbx1_p8(a: poly8x8_t, b: poly8x16_t, c: uint8x8_t) -> poly8x8_t { - unsafe { - let x = transmute(vqtbx1(transmute(a), transmute(b), c)); - x - } + unsafe { transmute(vqtbx1(transmute(a), transmute(b), c)) } } #[doc = "Extended table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx1q_p8)"] @@ -20433,10 +20412,7 @@ pub fn vqtbx1_p8(a: poly8x8_t, b: poly8x16_t, c: uint8x8_t) -> poly8x8_t { #[cfg_attr(test, assert_instr(tbx))] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqtbx1q_p8(a: poly8x16_t, b: poly8x16_t, c: uint8x16_t) -> poly8x16_t { - unsafe { - let x = transmute(vqtbx1q(transmute(a), transmute(b), c)); - x - } + unsafe { transmute(vqtbx1q(transmute(a), transmute(b), c)) } } #[doc = "Extended table look-up"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqtbx2)"] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index ca00e3cc83f4c..b4b98f0924450 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -12279,17 +12279,15 @@ intrinsics: - [poly8x8_t, "poly8x16_t", uint8x8_t, "vqtbx1", "_p8"] - [uint8x16_t, "uint8x16_t", uint8x16_t, "vqtbx1q", "q_u8"] - [poly8x16_t, "poly8x16_t", uint8x16_t, "vqtbx1q", "q_p8"] + big_endian_inverse: false compose: - - Let: - - x - - FnCall: - - transmute - - - FnCall: - - "{type[3]}" - - - FnCall: [transmute, [a]] - - FnCall: [transmute, [b]] - - c - - Identifier: [x, Symbol] + - FnCall: + - transmute + - - FnCall: + - "{type[3]}" + - - FnCall: [transmute, [a]] + - FnCall: [transmute, [b]] + - c - name: "vtbx1{neon_type[0].no}" doc: "Extended table look-up" @@ -12461,16 +12459,14 @@ intrinsics: - ['poly8x16_t', uint8x8_t, 'vqtbl1', 'poly8x8_t'] - ['uint8x16_t', uint8x16_t, 'vqtbl1q', 'uint8x16_t'] - ['poly8x16_t', uint8x16_t, 'vqtbl1q', 'poly8x16_t'] + big_endian_inverse: false compose: - - Let: - - x - - FnCall: - - transmute - - - FnCall: - - '{type[2]}' - - - FnCall: [transmute, ['a']] - - b - - Identifier: [x, Symbol] + - FnCall: + - transmute + - - FnCall: + - '{type[2]}' + - - FnCall: [transmute, ['a']] + - b - name: "vqtbl2{neon_type[3].no}" doc: "Table look-up" From 92701fef209b008a4b70a8e5ac093e18a4942d20 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 8 Jul 2025 08:45:56 +0200 Subject: [PATCH 19/36] shorten array literals --- .../src/arm_shared/neon/generated.rs | 104 +++--------------- .../spec/neon/arm_shared.spec.yml | 28 ++--- 2 files changed, 28 insertions(+), 104 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 286f1868852aa..4df1b741485b9 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -40758,16 +40758,7 @@ pub fn vqshlu_n_s8(a: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v8i8")] fn _vqshlu_n_s8(a: int8x8_t, n: int8x8_t) -> uint8x8_t; } - unsafe { - _vqshlu_n_s8( - a, - const { - int8x8_t([ - N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, - ]) - }, - ) - } + unsafe { _vqshlu_n_s8(a, const { int8x8_t([N as i8; 8]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshluq_n_s8)"] @@ -40783,17 +40774,7 @@ pub fn vqshluq_n_s8(a: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v16i8")] fn _vqshluq_n_s8(a: int8x16_t, n: int8x16_t) -> uint8x16_t; } - unsafe { - _vqshluq_n_s8( - a, - const { - int8x16_t([ - N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, - N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, - ]) - }, - ) - } + unsafe { _vqshluq_n_s8(a, const { int8x16_t([N as i8; 16]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s16)"] @@ -40809,12 +40790,7 @@ pub fn vqshlu_n_s16(a: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v4i16")] fn _vqshlu_n_s16(a: int16x4_t, n: int16x4_t) -> uint16x4_t; } - unsafe { - _vqshlu_n_s16( - a, - const { int16x4_t([N as i16, N as i16, N as i16, N as i16]) }, - ) - } + unsafe { _vqshlu_n_s16(a, const { int16x4_t([N as i16; 4]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshluq_n_s16)"] @@ -40830,16 +40806,7 @@ pub fn vqshluq_n_s16(a: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v8i16")] fn _vqshluq_n_s16(a: int16x8_t, n: int16x8_t) -> uint16x8_t; } - unsafe { - _vqshluq_n_s16( - a, - const { - int16x8_t([ - N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, - ]) - }, - ) - } + unsafe { _vqshluq_n_s16(a, const { int16x8_t([N as i16; 8]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s32)"] @@ -40855,7 +40822,7 @@ pub fn vqshlu_n_s32(a: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v2i32")] fn _vqshlu_n_s32(a: int32x2_t, n: int32x2_t) -> uint32x2_t; } - unsafe { _vqshlu_n_s32(a, const { int32x2_t([N as i32, N as i32]) }) } + unsafe { _vqshlu_n_s32(a, const { int32x2_t([N; 2]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshluq_n_s32)"] @@ -40871,12 +40838,7 @@ pub fn vqshluq_n_s32(a: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v4i32")] fn _vqshluq_n_s32(a: int32x4_t, n: int32x4_t) -> uint32x4_t; } - unsafe { - _vqshluq_n_s32( - a, - const { int32x4_t([N as i32, N as i32, N as i32, N as i32]) }, - ) - } + unsafe { _vqshluq_n_s32(a, const { int32x4_t([N; 4]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s64)"] @@ -40908,7 +40870,7 @@ pub fn vqshluq_n_s64(a: int64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqshiftsu.v2i64")] fn _vqshluq_n_s64(a: int64x2_t, n: int64x2_t) -> uint64x2_t; } - unsafe { _vqshluq_n_s64(a, const { int64x2_t([N as i64, N as i64]) }) } + unsafe { _vqshluq_n_s64(a, const { int64x2_t([N as i64; 2]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s8)"] @@ -40927,16 +40889,7 @@ pub fn vqshlu_n_s8(a: int8x8_t) -> uint8x8_t { )] fn _vqshlu_n_s8(a: int8x8_t, n: int8x8_t) -> uint8x8_t; } - unsafe { - _vqshlu_n_s8( - a, - const { - int8x8_t([ - N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, - ]) - }, - ) - } + unsafe { _vqshlu_n_s8(a, const { int8x8_t([N as i8; 8]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshluq_n_s8)"] @@ -40955,17 +40908,7 @@ pub fn vqshluq_n_s8(a: int8x16_t) -> uint8x16_t { )] fn _vqshluq_n_s8(a: int8x16_t, n: int8x16_t) -> uint8x16_t; } - unsafe { - _vqshluq_n_s8( - a, - const { - int8x16_t([ - N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, - N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, - ]) - }, - ) - } + unsafe { _vqshluq_n_s8(a, const { int8x16_t([N as i8; 16]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s16)"] @@ -40984,12 +40927,7 @@ pub fn vqshlu_n_s16(a: int16x4_t) -> uint16x4_t { )] fn _vqshlu_n_s16(a: int16x4_t, n: int16x4_t) -> uint16x4_t; } - unsafe { - _vqshlu_n_s16( - a, - const { int16x4_t([N as i16, N as i16, N as i16, N as i16]) }, - ) - } + unsafe { _vqshlu_n_s16(a, const { int16x4_t([N as i16; 4]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshluq_n_s16)"] @@ -41008,16 +40946,7 @@ pub fn vqshluq_n_s16(a: int16x8_t) -> uint16x8_t { )] fn _vqshluq_n_s16(a: int16x8_t, n: int16x8_t) -> uint16x8_t; } - unsafe { - _vqshluq_n_s16( - a, - const { - int16x8_t([ - N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, - ]) - }, - ) - } + unsafe { _vqshluq_n_s16(a, const { int16x8_t([N as i16; 8]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s32)"] @@ -41036,7 +40965,7 @@ pub fn vqshlu_n_s32(a: int32x2_t) -> uint32x2_t { )] fn _vqshlu_n_s32(a: int32x2_t, n: int32x2_t) -> uint32x2_t; } - unsafe { _vqshlu_n_s32(a, const { int32x2_t([N as i32, N as i32]) }) } + unsafe { _vqshlu_n_s32(a, const { int32x2_t([N; 2]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshluq_n_s32)"] @@ -41055,12 +40984,7 @@ pub fn vqshluq_n_s32(a: int32x4_t) -> uint32x4_t { )] fn _vqshluq_n_s32(a: int32x4_t, n: int32x4_t) -> uint32x4_t; } - unsafe { - _vqshluq_n_s32( - a, - const { int32x4_t([N as i32, N as i32, N as i32, N as i32]) }, - ) - } + unsafe { _vqshluq_n_s32(a, const { int32x4_t([N; 4]) }) } } #[doc = "Signed saturating shift left unsigned"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshlu_n_s64)"] @@ -41098,7 +41022,7 @@ pub fn vqshluq_n_s64(a: int64x2_t) -> uint64x2_t { )] fn _vqshluq_n_s64(a: int64x2_t, n: int64x2_t) -> uint64x2_t; } - unsafe { _vqshluq_n_s64(a, const { int64x2_t([N as i64, N as i64]) }) } + unsafe { _vqshluq_n_s64(a, const { int64x2_t([N as i64; 2]) }) } } #[doc = "Signed saturating shift right narrow"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqshrn_n_s16)"] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 118f5808f758f..07959cf380e8a 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -11447,14 +11447,14 @@ intrinsics: static_defs: ['const N: i32'] safety: safe types: - - [int8x8_t, uint8x8_t, '3', 'const { int8x8_t([N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8]) }'] - - [int16x4_t, uint16x4_t, '4', 'const { int16x4_t([N as i16, N as i16, N as i16, N as i16]) }'] - - [int32x2_t, uint32x2_t, '5', 'const { int32x2_t([N as i32, N as i32]) }'] + - [int8x8_t, uint8x8_t, '3', 'const { int8x8_t([N as i8; 8]) }'] + - [int16x4_t, uint16x4_t, '4', 'const { int16x4_t([N as i16; 4]) }'] + - [int32x2_t, uint32x2_t, '5', 'const { int32x2_t([N; 2]) }'] - [int64x1_t, uint64x1_t, '6', 'const { int64x1_t([N as i64]) }'] - - [int8x16_t, uint8x16_t, '3', 'const { int8x16_t([N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8]) }'] - - [int16x8_t, uint16x8_t, '4', 'const { int16x8_t([N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16]) }'] - - [int32x4_t, uint32x4_t, '5', 'const { int32x4_t([N as i32, N as i32, N as i32, N as i32]) }'] - - [int64x2_t, uint64x2_t, '6', 'const { int64x2_t([N as i64, N as i64]) }'] + - [int8x16_t, uint8x16_t, '3', 'const { int8x16_t([N as i8; 16]) }'] + - [int16x8_t, uint16x8_t, '4', 'const { int16x8_t([N as i16; 8]) }'] + - [int32x4_t, uint32x4_t, '5', 'const { int32x4_t([N; 4]) }'] + - [int64x2_t, uint64x2_t, '6', 'const { int64x2_t([N as i64; 2]) }'] compose: - FnCall: [static_assert_uimm_bits!, [N, "{type[2]}"]] - LLVMLink: @@ -11479,14 +11479,14 @@ intrinsics: static_defs: ['const N: i32'] safety: safe types: - - [int8x8_t, uint8x8_t, '3', 'const { int8x8_t([N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8]) }'] - - [int16x4_t, uint16x4_t, '4', 'const { int16x4_t([N as i16, N as i16, N as i16, N as i16]) }'] - - [int32x2_t, uint32x2_t, '5', 'const { int32x2_t([N as i32, N as i32]) }'] + - [int8x8_t, uint8x8_t, '3', 'const { int8x8_t([N as i8; 8]) }'] + - [int16x4_t, uint16x4_t, '4', 'const { int16x4_t([N as i16; 4]) }'] + - [int32x2_t, uint32x2_t, '5', 'const { int32x2_t([N; 2]) }'] - [int64x1_t, uint64x1_t, '6', 'const { int64x1_t([N as i64]) }'] - - [int8x16_t, uint8x16_t, '3', 'const { int8x16_t([N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N as i8]) }'] - - [int16x8_t, uint16x8_t, '4', 'const { int16x8_t([N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16, N as i16]) }'] - - [int32x4_t, uint32x4_t, '5', 'const { int32x4_t([N as i32, N as i32, N as i32, N as i32]) }'] - - [int64x2_t, uint64x2_t, '6', 'const { int64x2_t([N as i64, N as i64]) }'] + - [int8x16_t, uint8x16_t, '3', 'const { int8x16_t([N as i8; 16]) }'] + - [int16x8_t, uint16x8_t, '4', 'const { int16x8_t([N as i16; 8]) }'] + - [int32x4_t, uint32x4_t, '5', 'const { int32x4_t([N; 4]) }'] + - [int64x2_t, uint64x2_t, '6', 'const { int64x2_t([N as i64; 2]) }'] compose: - FnCall: [static_assert_uimm_bits!, [N, "{type[2]}"]] - LLVMLink: From 061a941adc570ed717dfa2f3508a9038b8300eca Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 8 Jul 2025 08:48:13 +0200 Subject: [PATCH 20/36] remove unneeded cast --- .../stdarch/crates/core_arch/src/aarch64/neon/generated.rs | 4 ++-- .../stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index c23dd1c8a109a..32f144bc7adc4 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -17158,7 +17158,7 @@ pub fn vqdmlalh_s16(a: i32, b: i16, c: i16) -> i32 { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqdmlals_s32(a: i64, b: i32, c: i32) -> i64 { let x: i64 = vqaddd_s64(a, vqdmulls_s32(b, c)); - x as i64 + x } #[doc = "Signed saturating doubling multiply-subtract long"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqdmlsl_high_lane_s16)"] @@ -17324,7 +17324,7 @@ pub fn vqdmlslh_s16(a: i32, b: i16, c: i16) -> i32 { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vqdmlsls_s32(a: i64, b: i32, c: i32) -> i64 { let x: i64 = vqsubd_s64(a, vqdmulls_s32(b, c)); - x as i64 + x } #[doc = "Vector saturating doubling multiply high by scalar"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vqdmulh_lane_s16)"] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index b4b98f0924450..f0dce681d9c30 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -7312,7 +7312,7 @@ intrinsics: - ["i64", "i32", "i32", "i64"] compose: - Let: [x, i64, {FnCall: [vqaddd_s64, [a, {FnCall: [vqdmulls_s32, [b, c]]}]]}] - - Identifier: ['x as i64', Symbol] + - Identifier: ['x', Symbol] - name: "vqdmlal{type[4]}" doc: "Signed saturating doubling multiply-add long" @@ -7426,7 +7426,7 @@ intrinsics: - ["i64", "i32", "i32", "i64"] compose: - Let: [x, i64, {FnCall: [vqsubd_s64, [a, {FnCall: [vqdmulls_s32, [b, c]]}]]}] - - Identifier: ['x as i64', Symbol] + - Identifier: ['x', Symbol] - name: "vqdmlsl{type[4]}" doc: "Signed saturating doubling multiply-subtract long" From 701d222e3f908d37082c6896c6e91b9fb9466607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 8 Jul 2025 16:18:43 +0200 Subject: [PATCH 21/36] Reset rust-version --- library/stdarch/rust-version | 1 - 1 file changed, 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 56a727c28200f..e69de29bb2d1d 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +0,0 @@ -1b61d43bdbf875183b1f436302d62ff93f9a6bba From 3c9297c845c513a2609dd915ca9346664fe82663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 8 Jul 2025 16:18:46 +0200 Subject: [PATCH 22/36] Prepare for merging from rust-lang/rust This updates the rust-version file to 040e2f8b9ff2d76fbe2146d6003e297ed4532088. --- library/stdarch/rust-version | 1 + 1 file changed, 1 insertion(+) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index e69de29bb2d1d..5102178848e7f 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -0,0 +1 @@ +040e2f8b9ff2d76fbe2146d6003e297ed4532088 From d54c3ea65c432743d7630ad3c1e16a94fb493fae Mon Sep 17 00:00:00 2001 From: Sebastian Poeplau Date: Thu, 3 Jul 2025 17:02:40 +0200 Subject: [PATCH 23/36] Preserve the .debug_gdb_scripts section Make sure that compiler and linker don't optimize the section's contents away by adding the global holding the data to "llvm.used". This eliminates the need for a volatile load in the main shim; since the LLVM codegen backend is the only implementer of the corresponding trait function, remove it entirely. --- compiler/rustc_codegen_gcc/src/debuginfo.rs | 7 ++-- compiler/rustc_codegen_llvm/src/base.rs | 12 +++---- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 28 ++++++--------- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 34 +++++++++---------- compiler/rustc_codegen_ssa/src/base.rs | 2 -- .../rustc_codegen_ssa/src/traits/debuginfo.rs | 3 +- tests/codegen/gdb_debug_script_load.rs | 26 ++------------ 7 files changed, 39 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 4c8585192a1b1..51b2cd31fe612 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -36,10 +36,6 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { _variable_alloca.set_location(_dbg_loc); } - fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { - // TODO(antoyo): insert reference to gdb debug scripts section global. - } - /// FIXME(tempdragon): Currently, this function is not yet implemented. It seems that the /// debug name and the mangled name should both be included in the LValues. /// Besides, a function to get the rvalue type(m_is_lvalue) should also be included. @@ -254,7 +250,8 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // TODO(antoyo): implement. } - fn debuginfo_finalize(&self) { + fn debuginfo_finalize(&mut self) { + // TODO: emit section `.debug_gdb_scripts`. self.context.set_debug_info(true) } diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 5dda836988c81..d7da03bf490fd 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -109,11 +109,16 @@ pub(crate) fn compile_codegen_unit( } // Finalize code coverage by injecting the coverage map. Note, the coverage map will - // also be added to the `llvm.compiler.used` variable, created next. + // also be added to the `llvm.compiler.used` variable, created below. if cx.sess().instrument_coverage() { cx.coverageinfo_finalize(); } + // Finalize debuginfo. This adds to `llvm.used`, created below. + if cx.sess().opts.debuginfo != DebugInfo::None { + cx.debuginfo_finalize(); + } + // Create the llvm.used and llvm.compiler.used variables. if !cx.used_statics.is_empty() { cx.create_used_variable_impl(c"llvm.used", &cx.used_statics); @@ -130,11 +135,6 @@ pub(crate) fn compile_codegen_unit( llvm::LLVMDeleteGlobal(old_g); } } - - // Finalize debuginfo - if cx.sess().opts.debuginfo != DebugInfo::None { - cx.debuginfo_finalize(); - } } ModuleCodegen::new_regular(cgu_name.to_string(), llvm_module) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 8f0948b8183bf..6e614c372be87 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -1,5 +1,7 @@ // .debug_gdb_scripts binary section. +use std::ffi::CString; + use rustc_ast::attr; use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive; use rustc_codegen_ssa::traits::*; @@ -9,31 +11,21 @@ use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerType; use rustc_session::config::{CrateType, DebugInfo}; use rustc_span::sym; -use crate::builder::Builder; use crate::common::CodegenCx; use crate::llvm; use crate::value::Value; -/// Inserts a side-effect free instruction sequence that makes sure that the -/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker. -pub(crate) fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) { - if needs_gdb_debug_scripts_section(bx) { - let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx); - // Load just the first byte as that's all that's necessary to force - // LLVM to keep around the reference to the global. - let volatile_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section); - unsafe { - llvm::LLVMSetAlignment(volatile_load_instruction, 1); - } - } -} - /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( - cx: &CodegenCx<'ll, '_>, + cx: &mut CodegenCx<'ll, '_>, ) -> &'ll Value { - let c_section_var_name = c"__rustc_debug_gdb_scripts_section__"; + let c_section_var_name = CString::new(format!( + "__rustc_debug_gdb_scripts_section_{}_{:08x}", + cx.tcx.crate_name(LOCAL_CRATE), + cx.tcx.stable_crate_id(LOCAL_CRATE), + )) + .unwrap(); let section_var_name = c_section_var_name.to_str().unwrap(); let section_var = unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr()) }; @@ -80,6 +72,8 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( // This should make sure that the whole section is not larger than // the string it contains. Otherwise we get a warning from GDB. llvm::LLVMSetAlignment(section_var, 1); + // Make sure that the linker doesn't optimize the global away. + cx.add_used_global(section_var); section_var } }) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 5ca2505cec43b..1e3d4275a3fc3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -30,7 +30,7 @@ use tracing::debug; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, type_di_node}; use self::namespace::mangled_name_of_instance; -use self::utils::{DIB, create_DIArray, is_node_local_to_unit}; +use self::utils::{DIB, create_DIArray, debug_context, is_node_local_to_unit}; use crate::builder::Builder; use crate::common::{AsCCharPtr, CodegenCx}; use crate::llvm; @@ -131,20 +131,22 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { } /// Creates any deferred debug metadata nodes -pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { - if let Some(dbg_cx) = &cx.dbg_cx { - debug!("finalize"); - - if gdb::needs_gdb_debug_scripts_section(cx) { - // Add a .debug_gdb_scripts section to this compile-unit. This will - // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, - // which activates the Rust pretty printers for binary this section is - // contained in. - gdb::get_or_insert_gdb_debug_scripts_section_global(cx); - } +pub(crate) fn finalize(cx: &mut CodegenCx<'_, '_>) { + if cx.dbg_cx.is_none() { + return; + } + + debug!("finalize"); - dbg_cx.finalize(cx.sess()); + if gdb::needs_gdb_debug_scripts_section(cx) { + // Add a .debug_gdb_scripts section to this compile-unit. This will + // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, + // which activates the Rust pretty printers for binary this section is + // contained in. + gdb::get_or_insert_gdb_debug_scripts_section_global(cx); } + + debug_context(cx).finalize(cx.sess()); } impl<'ll> Builder<'_, 'll, '_> { @@ -215,10 +217,6 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { } } - fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { - gdb::insert_reference_to_gdb_debug_scripts_section_global(self) - } - fn set_var_name(&mut self, value: &'ll Value, name: &str) { // Avoid wasting time if LLVM value names aren't even enabled. if self.sess().fewer_names() { @@ -614,7 +612,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { metadata::extend_scope_to_file(self, scope_metadata, file) } - fn debuginfo_finalize(&self) { + fn debuginfo_finalize(&mut self) { finalize(self) } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 18581f854b664..5cdbf7be528a5 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -528,8 +528,6 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let llbb = Bx::append_block(cx, llfn, "top"); let mut bx = Bx::build(cx, llbb); - bx.insert_reference_to_gdb_debug_scripts_section_global(); - let isize_ty = cx.type_isize(); let ptr_ty = cx.type_ptr(); let (arg_argc, arg_argv) = get_argc_argv(&mut bx); diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index b9d4950e0ad36..e5dfe0b2cda48 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -50,7 +50,7 @@ pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes { scope_metadata: Self::DIScope, file: &SourceFile, ) -> Self::DIScope; - fn debuginfo_finalize(&self); + fn debuginfo_finalize(&mut self); // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). @@ -81,6 +81,5 @@ pub trait DebugInfoBuilderMethods: BackendTypes { ); fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation); fn clear_dbg_loc(&mut self); - fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); fn set_var_name(&mut self, value: Self::Value, name: &str); } diff --git a/tests/codegen/gdb_debug_script_load.rs b/tests/codegen/gdb_debug_script_load.rs index 3e92eba10b121..cc7170460ed32 100644 --- a/tests/codegen/gdb_debug_script_load.rs +++ b/tests/codegen/gdb_debug_script_load.rs @@ -4,34 +4,14 @@ //@ ignore-wasm //@ ignore-emscripten -//@ compile-flags: -g -C no-prepopulate-passes -Cpanic=abort +//@ compile-flags: -g -Cpanic=abort -#![feature(lang_items)] #![no_std] +#![no_main] #[panic_handler] fn panic_handler(_: &core::panic::PanicInfo) -> ! { loop {} } -#[no_mangle] -extern "C" fn rust_eh_personality() { - loop {} -} - -// Needs rustc to generate `main` as that's where the magic load is inserted. -// IOW, we cannot write this test with `#![no_main]`. -// CHECK-LABEL: @main -// CHECK: load volatile i8, {{.+}} @__rustc_debug_gdb_scripts_section__ - -#[lang = "start"] -fn lang_start( - _main: fn() -> T, - _argc: isize, - _argv: *const *const u8, - _sigpipe: u8, -) -> isize { - return 0; -} - -fn main() {} +// CHECK: @llvm.used = {{.+}} @__rustc_debug_gdb_scripts_section From e47eb3275dcd6eac2c3c24f352600763d0bfd814 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 17 Oct 2024 04:58:36 +0100 Subject: [PATCH 24/36] Rename `*AsmOperandRef::Const` to `Interpolate` This is used for string interpolation currently, so rename it as so. The name `Const` will be used to denote a general CTFE constant that can either be integer or pointer. --- compiler/rustc_codegen_cranelift/src/global_asm.rs | 2 +- compiler/rustc_codegen_gcc/src/asm.rs | 8 ++++---- compiler/rustc_codegen_llvm/src/asm.rs | 4 ++-- compiler/rustc_codegen_ssa/src/base.rs | 4 ++-- compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/naked_asm.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/asm.rs | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 203b443269fa7..3cf402f20dc09 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -104,7 +104,7 @@ fn codegen_global_asm_inner<'tcx>( InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { match operands[operand_idx] { - GlobalAsmOperandRef::Const { ref string } => { + GlobalAsmOperandRef::Interpolate { ref string } => { global_asm.push_str(string); } GlobalAsmOperandRef::SymFn { instance } => { diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 17e2e028b16fa..82b132870d47e 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -296,7 +296,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } } - InlineAsmOperandRef::Const { ref string } => { + InlineAsmOperandRef::Interpolate { ref string } => { constants_len += string.len() + att_dialect as usize; } @@ -411,7 +411,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { }); } - InlineAsmOperandRef::Const { .. } => { + InlineAsmOperandRef::Interpolate { .. } => { // processed in the previous pass } @@ -504,7 +504,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(name); } - InlineAsmOperandRef::Const { ref string } => { + InlineAsmOperandRef::Interpolate { ref string } => { template_str.push_str(string); } @@ -868,7 +868,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { match operands[operand_idx] { - GlobalAsmOperandRef::Const { ref string } => { + GlobalAsmOperandRef::Interpolate { ref string } => { // Const operands get injected directly into the // template. Note that we don't need to escape % // here unlike normal inline assembly. diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 9ddadcf16aa3d..ede40c8fef323 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -205,7 +205,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { template_str.push_str(&format!("${{{}}}", op_idx[&operand_idx])); } } - InlineAsmOperandRef::Const { ref string } => { + InlineAsmOperandRef::Interpolate { ref string } => { // Const operands get injected directly into the template template_str.push_str(string); } @@ -398,7 +398,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { match operands[operand_idx] { - GlobalAsmOperandRef::Const { ref string } => { + GlobalAsmOperandRef::Interpolate { ref string } => { // Const operands get injected directly into the // template. Note that we don't need to escape $ // here unlike normal inline assembly. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 18581f854b664..da6d4e4c12cac 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -415,14 +415,14 @@ where const_value, cx.layout_of(ty), ); - GlobalAsmOperandRef::Const { string } + GlobalAsmOperandRef::Interpolate { string } } Err(ErrorHandled::Reported { .. }) => { // An error has already been reported and // compilation is guaranteed to fail if execution // hits this path. So an empty string instead of // a stringified constant value will suffice. - GlobalAsmOperandRef::Const { string: String::new() } + GlobalAsmOperandRef::Interpolate { string: String::new() } } Err(ErrorHandled::TooGeneric(_)) => { span_bug!(*op_sp, "asm const cannot be resolved; too generic") diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index bde63fd501aa2..a021f12cf8c85 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1193,7 +1193,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { const_value, bx.layout_of(value.ty()), ); - InlineAsmOperandRef::Const { string } + InlineAsmOperandRef::Interpolate { string } } mir::InlineAsmOperand::SymFn { ref value } => { let const_ = self.monomorphize(value.const_); diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index beaf895097842..73627405c1576 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -84,7 +84,7 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL cx.layout_of(mono_type), ); - GlobalAsmOperandRef::Const { string } + GlobalAsmOperandRef::Interpolate { string } } InlineAsmOperand::SymFn { value } => { let mono_type = instance.instantiate_mir_and_normalize_erasing_regions( diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index cc7a6a3f19e9e..5af433cd95f65 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -25,7 +25,7 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { in_value: OperandRef<'tcx, B::Value>, out_place: Option>, }, - Const { + Interpolate { string: String, }, SymFn { @@ -41,7 +41,7 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { #[derive(Debug)] pub enum GlobalAsmOperandRef<'tcx> { - Const { string: String }, + Interpolate { string: String }, SymFn { instance: Instance<'tcx> }, SymStatic { def_id: DefId }, } From 202815702981b2396a1f6305bbdc5288b4603d7d Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 17 Oct 2024 08:31:35 +0100 Subject: [PATCH 25/36] Add `InlineAsmOperandRef::Const` This is intended for supporting passing arbitrary CTFE const into inline assembly. --- compiler/rustc_codegen_gcc/src/asm.rs | 21 ++++++++++++++++++++ compiler/rustc_codegen_llvm/src/asm.rs | 8 ++++++++ compiler/rustc_codegen_ssa/src/traits/asm.rs | 9 +++++++++ 3 files changed, 38 insertions(+) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 82b132870d47e..85cff9b5afad8 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -300,6 +300,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { constants_len += string.len() + att_dialect as usize; } + InlineAsmOperandRef::Const { value } => { + inputs.push(AsmInOperand { + constraint: Cow::Borrowed("i"), + rust_idx, + val: value.immediate(), + }); + } + InlineAsmOperandRef::SymFn { instance } => { // TODO(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O) @@ -415,6 +423,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // processed in the previous pass } + InlineAsmOperandRef::Const { .. } => { + // processed in the previous pass + } + InlineAsmOperandRef::Label { .. } => { // processed in the previous pass } @@ -488,6 +500,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { push_to_template(modifier, gcc_index); } + InlineAsmOperandRef::Const { .. } => { + let in_gcc_index = inputs + .iter() + .position(|op| operand_idx == op.rust_idx) + .expect("wrong rust index"); + let gcc_index = in_gcc_index + outputs.len(); + push_to_template(None, gcc_index); + } + InlineAsmOperandRef::SymFn { instance } => { // TODO(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index ede40c8fef323..b1fcda68ffc56 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -158,6 +158,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { constraints.push(format!("{}", op_idx[&idx])); } } + InlineAsmOperandRef::Const { value } => { + inputs.push(value.immediate()); + op_idx.insert(idx, constraints.len()); + constraints.push("i".to_string()); + } InlineAsmOperandRef::SymFn { instance } => { inputs.push(self.cx.get_fn(instance)); op_idx.insert(idx, constraints.len()); @@ -205,6 +210,9 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { template_str.push_str(&format!("${{{}}}", op_idx[&operand_idx])); } } + InlineAsmOperandRef::Const { .. } => { + template_str.push_str(&format!("${{{}:c}}", op_idx[&operand_idx])); + } InlineAsmOperandRef::Interpolate { ref string } => { // Const operands get injected directly into the template template_str.push_str(string); diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index 5af433cd95f65..84319f2bcd281 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -25,9 +25,18 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { in_value: OperandRef<'tcx, B::Value>, out_place: Option>, }, + /// Interpolate a string directly into the inline assembly. + /// + /// This is distinct from `Const`, which can reference a const pointer or reference (and thus is + /// a const in Rust/linker sense but not a literal value). + /// + /// We currently use this for constant integers. They could technically use `Const` as well. Interpolate { string: String, }, + Const { + value: OperandRef<'tcx, B::Value>, + }, SymFn { instance: Instance<'tcx>, }, From b38ec0dd6e8e79ef1427c72673941b7085d127cf Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 24 Oct 2024 06:22:18 +0100 Subject: [PATCH 26/36] Implement asm_const_ptr for inline asm --- compiler/rustc_codegen_ssa/src/mir/block.rs | 21 ++++++---- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_typeck/messages.ftl | 4 ++ compiler/rustc_hir_typeck/src/errors.rs | 7 ++++ compiler/rustc_hir_typeck/src/inline_asm.rs | 35 ++++++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/asm/const-refs-to-static.rs | 9 +++-- tests/ui/asm/const-refs-to-static.stderr | 22 ----------- tests/ui/asm/invalid-const-operand.rs | 6 +-- tests/ui/asm/invalid-const-operand.stderr | 38 +++++-------------- .../feature-gate-asm_const_ptr.rs | 10 +++++ .../feature-gate-asm_const_ptr.stderr | 13 +++++++ 12 files changed, 100 insertions(+), 68 deletions(-) delete mode 100644 tests/ui/asm/const-refs-to-static.stderr create mode 100644 tests/ui/feature-gates/feature-gate-asm_const_ptr.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a021f12cf8c85..752980358837d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1186,14 +1186,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { InlineAsmOperandRef::InOut { reg, late, in_value, out_place } } mir::InlineAsmOperand::Const { ref value } => { - let const_value = self.eval_mir_constant(value); - let string = common::asm_const_to_str( - bx.tcx(), - span, - const_value, - bx.layout_of(value.ty()), - ); - InlineAsmOperandRef::Interpolate { string } + if value.ty().is_any_ptr() { + let value = self.eval_mir_constant_to_operand(bx, value); + InlineAsmOperandRef::Const { value } + } else { + let const_value = self.eval_mir_constant(value); + let string = common::asm_const_to_str( + bx.tcx(), + span, + const_value, + bx.layout_of(value.ty()), + ); + InlineAsmOperandRef::Interpolate { string } + } } mir::InlineAsmOperand::SymFn { ref value } => { let const_ = self.monomorphize(value.const_); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index efd8bde71d76d..d0d4a39d80ad7 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -377,6 +377,8 @@ declare_features! ( (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), /// Allows #[cfg(...)] on inline assembly templates and operands. (unstable, asm_cfg, "1.89.0", Some(140364)), + /// Allows using `const` operands with pointer in inline assembly. + (unstable, asm_const_ptr, "CURRENT_RUSTC_VERSION", Some(128464)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Enables experimental register support in inline assembly. diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index c21b16c9f9f04..a2ed8d75f4368 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -15,6 +15,10 @@ hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new hir_typeck_as_deref_suggestion = consider using `as_deref` here + +hir_typeck_asm_const_ptr_unstable = + using pointers in asm `const` operand is experimental + hir_typeck_base_expression_double_dot = base expression required after `..` hir_typeck_base_expression_double_dot_add_expr = add a base expression here hir_typeck_base_expression_double_dot_enable_default_field_values = diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 3606c778fc407..bdf29339e99f1 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -18,6 +18,13 @@ use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; +#[derive(Diagnostic)] +#[diag(hir_typeck_asm_const_ptr_unstable)] +pub(crate) struct AsmConstPtrUnstable { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(hir_typeck_base_expression_double_dot, code = E0797)] pub(crate) struct BaseExpressionDoubleDot { diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index b59c1752c25ad..91423c1acef9e 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -14,7 +14,7 @@ use rustc_target::asm::{ use rustc_trait_selection::infer::InferCtxtExt; use crate::FnCtxt; -use crate::errors::RegisterTypeUnstable; +use crate::errors::{AsmConstPtrUnstable, RegisterTypeUnstable}; pub(crate) struct InlineAsmCtxt<'a, 'tcx> { target_features: &'tcx FxIndexSet, @@ -511,7 +511,36 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { match ty.kind() { ty::Error(_) => {} _ if ty.is_integral() => {} + ty::FnPtr(..) => { + if !self.tcx().features().asm_const_ptr() { + self.tcx() + .sess + .create_feature_err( + AsmConstPtrUnstable { span: op_sp }, + sym::asm_const_ptr, + ) + .emit(); + } + } + ty::RawPtr(pointee, _) | ty::Ref(_, pointee, _) + if self.is_thin_ptr_ty(op_sp, *pointee) => + { + if !self.tcx().features().asm_const_ptr() { + self.tcx() + .sess + .create_feature_err( + AsmConstPtrUnstable { span: op_sp }, + sym::asm_const_ptr, + ) + .emit(); + } + } _ => { + let const_possible_ty = if !self.tcx().features().asm_const_ptr() { + "integer" + } else { + "integer or thin pointer" + }; self.fcx .dcx() .struct_span_err(op_sp, "invalid type for `const` operand") @@ -519,7 +548,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { self.tcx().def_span(anon_const.def_id), format!("is {} `{}`", ty.kind().article(), ty), ) - .with_help("`const` operands must be of an integer type") + .with_help(format!( + "`const` operands must be of an {const_possible_ty} type" + )) .emit(); } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 09f01d8704e2a..a98a39e27e9d5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -468,6 +468,7 @@ symbols! { asm, asm_cfg, asm_const, + asm_const_ptr, asm_experimental_arch, asm_experimental_reg, asm_goto, diff --git a/tests/ui/asm/const-refs-to-static.rs b/tests/ui/asm/const-refs-to-static.rs index ce2c5b3246ec8..8058d70550aba 100644 --- a/tests/ui/asm/const-refs-to-static.rs +++ b/tests/ui/asm/const-refs-to-static.rs @@ -1,19 +1,20 @@ //@ needs-asm-support //@ ignore-nvptx64 //@ ignore-spirv +//@ build-pass + +#![feature(asm_const_ptr)] use std::arch::{asm, global_asm}; use std::ptr::addr_of; static FOO: u8 = 42; -global_asm!("{}", const addr_of!(FOO)); -//~^ ERROR invalid type for `const` operand +global_asm!("/* {} */", const addr_of!(FOO)); #[no_mangle] fn inline() { - unsafe { asm!("{}", const addr_of!(FOO)) }; - //~^ ERROR invalid type for `const` operand + unsafe { asm!("/* {} */", const addr_of!(FOO)) }; } fn main() {} diff --git a/tests/ui/asm/const-refs-to-static.stderr b/tests/ui/asm/const-refs-to-static.stderr deleted file mode 100644 index 10e1ca5bd6068..0000000000000 --- a/tests/ui/asm/const-refs-to-static.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: invalid type for `const` operand - --> $DIR/const-refs-to-static.rs:10:19 - | -LL | global_asm!("{}", const addr_of!(FOO)); - | ^^^^^^------------- - | | - | is a `*const u8` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/const-refs-to-static.rs:15:25 - | -LL | unsafe { asm!("{}", const addr_of!(FOO)) }; - | ^^^^^^------------- - | | - | is a `*const u8` - | - = help: `const` operands must be of an integer type - -error: aborting due to 2 previous errors - diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs index bbf4001752a4b..e8f437196ec1c 100644 --- a/tests/ui/asm/invalid-const-operand.rs +++ b/tests/ui/asm/invalid-const-operand.rs @@ -2,6 +2,8 @@ //@ ignore-nvptx64 //@ ignore-spirv +#![feature(asm_const_ptr)] + use std::arch::{asm, global_asm}; // Const operands must be integers and must be constants. @@ -12,7 +14,6 @@ global_asm!("{}", const 0i128); global_asm!("{}", const 0f32); //~^ ERROR invalid type for `const` operand global_asm!("{}", const 0 as *mut u8); -//~^ ERROR invalid type for `const` operand fn test1() { unsafe { @@ -24,8 +25,7 @@ fn test1() { asm!("{}", const 0f32); //~^ ERROR invalid type for `const` operand asm!("{}", const 0 as *mut u8); - //~^ ERROR invalid type for `const` operand - asm!("{}", const &0); + asm!("{}", const b"Foo".as_slice()); //~^ ERROR invalid type for `const` operand } } diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr index 01aa843c6fb19..d09571a49221a 100644 --- a/tests/ui/asm/invalid-const-operand.stderr +++ b/tests/ui/asm/invalid-const-operand.stderr @@ -35,55 +35,35 @@ LL + const x: /* Type */ = 0; | error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:12:19 + --> $DIR/invalid-const-operand.rs:14:19 | LL | global_asm!("{}", const 0f32); | ^^^^^^---- | | | is an `f32` | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:14:19 - | -LL | global_asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type + = help: `const` operands must be of an integer or thin pointer type error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:24:20 + --> $DIR/invalid-const-operand.rs:25:20 | LL | asm!("{}", const 0f32); | ^^^^^^---- | | | is an `f32` | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:26:20 - | -LL | asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type + = help: `const` operands must be of an integer or thin pointer type error: invalid type for `const` operand --> $DIR/invalid-const-operand.rs:28:20 | -LL | asm!("{}", const &0); - | ^^^^^^-- +LL | asm!("{}", const b"Foo".as_slice()); + | ^^^^^^----------------- | | - | is a `&i32` + | is a `&[u8]` | - = help: `const` operands must be of an integer type + = help: `const` operands must be of an integer or thin pointer type -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs b/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs new file mode 100644 index 0000000000000..cc124ae39a399 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs @@ -0,0 +1,10 @@ +//@ only-x86_64 + +use std::arch::asm; + +fn main() { + unsafe { + asm!("/* {} */", const &0); + //~^ ERROR using pointers in asm `const` operand is experimental + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr b/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr new file mode 100644 index 0000000000000..8cc21dd853b49 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr @@ -0,0 +1,13 @@ +error[E0658]: using pointers in asm `const` operand is experimental + --> $DIR/feature-gate-asm_const_ptr.rs:7:26 + | +LL | asm!("/* {} */", const &0); + | ^^^^^^^^ + | + = note: see issue #128464 for more information + = help: add `#![feature(asm_const_ptr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 60179d3e693e965e233e9b8a15ad6a2ba81222af Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 12 Mar 2025 21:22:03 +0000 Subject: [PATCH 27/36] Give global_asm mangled names `global_asm!` themselves don't need symbol names; they currently only have a symbol name during mono collecion to identify them to partitioning algorithm. However it will have shims generated under it which will need unique symbol names. The name themselves ultimately doesn't matter, so they're generated like other shim instances. --- compiler/rustc_middle/src/mir/mono.rs | 2 +- compiler/rustc_symbol_mangling/src/legacy.rs | 5 +++++ compiler/rustc_symbol_mangling/src/v0.rs | 11 ++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 47ba850d50dd4..5e849597ca66c 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -121,7 +121,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::Fn(instance) => tcx.symbol_name(instance), MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)), MonoItem::GlobalAsm(item_id) => { - SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.owner_id)) + tcx.symbol_name(Instance::mono(tcx, item_id.owner_id.to_def_id())) } } } diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 12d1de463136a..90965000d6fa6 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -36,6 +36,11 @@ pub(super) fn mangle<'tcx>( debug!(?instance_ty); break; } + DefPathData::GlobalAsm => { + // `global_asm!` doesn't have a type. + instance_ty = tcx.types.unit; + break; + } _ => { // if we're making a symbol for something, there ought // to be a value or type-def or something in there diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index fe0f8e6113ef7..51e653a9ab31e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -867,6 +867,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // are effectively living in their parent modules. DefPathData::ForeignMod => return print_prefix(self), + // Global asm are handled similar to shims. + DefPathData::GlobalAsm => { + return self.path_append_ns( + print_prefix, + 'S', + disambiguated_data.disambiguator as u64, + "global_asm", + ); + } + // Uppercase categories are more stable than lowercase ones. DefPathData::TypeNs(_) => 't', DefPathData::ValueNs(_) => 'v', @@ -880,7 +890,6 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // These should never show up as `path_append` arguments. DefPathData::CrateRoot | DefPathData::Use - | DefPathData::GlobalAsm | DefPathData::Impl | DefPathData::MacroNs(_) | DefPathData::LifetimeNs(_) From 363fd499130e1de2590adb9624a7810d332ae027 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 12 Mar 2025 22:48:32 +0000 Subject: [PATCH 28/36] Collect constants within `global_asm!` in collector This is currently a no-op, but will be useful when const in `global_asm!` can be pointers. --- compiler/rustc_monomorphize/src/collector.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 131064f9832c0..68627a45b97b7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -486,10 +486,19 @@ fn collect_items_rec<'tcx>( if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind { for (op, op_sp) in asm.operands { match *op { - hir::InlineAsmOperand::Const { .. } => { - // Only constants which resolve to a plain integer - // are supported. Therefore the value should not - // depend on any other items. + hir::InlineAsmOperand::Const { anon_const } => { + match tcx.const_eval_poly(anon_const.def_id.to_def_id()) { + Ok(val) => { + collect_const_value(tcx, val, &mut used_items); + } + Err(ErrorHandled::TooGeneric(..)) => { + span_bug!(*op_sp, "asm const cannot be resolved; too generic") + } + Err(err @ ErrorHandled::Reported(..)) => { + err.emit_note(tcx); + continue; + } + } } hir::InlineAsmOperand::SymFn { expr } => { let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr); From 81a4b3efde1d2f4b2483d5747596f54fca214487 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 14 Mar 2025 16:36:59 +0000 Subject: [PATCH 29/36] Implement asm_const_ptr for global_asm and naked_asm --- .../rustc_codegen_cranelift/src/global_asm.rs | 9 +- compiler/rustc_codegen_gcc/src/asm.rs | 125 ++++++++++++---- compiler/rustc_codegen_llvm/src/asm.rs | 140 ++++++++++++++---- compiler/rustc_codegen_ssa/src/base.rs | 40 +++-- compiler/rustc_codegen_ssa/src/common.rs | 2 +- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 34 +++-- compiler/rustc_codegen_ssa/src/traits/asm.rs | 4 + compiler/rustc_monomorphize/src/collector.rs | 3 +- tests/assembly/asm/global_asm.rs | 5 + tests/assembly/asm/x86-types.rs | 14 +- tests/ui/asm/invalid-const-operand.rs | 7 +- tests/ui/asm/invalid-const-operand.stderr | 20 ++- .../feature-gate-asm_const_ptr.rs | 14 +- .../feature-gate-asm_const_ptr.stderr | 24 ++- 14 files changed, 345 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 3cf402f20dc09..ec9d00f92e5d5 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -8,10 +8,10 @@ use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::traits::{AsmCodegenMethods, GlobalAsmOperandRef}; -use rustc_middle::ty::TyCtxt; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; +use rustc_middle::ty::{Instance, TyCtxt}; use rustc_session::config::{OutputFilenames, OutputType}; use rustc_target::asm::InlineAsmArch; @@ -29,6 +29,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> { operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span], + _instance: Instance<'_>, ) { codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options); } @@ -132,6 +133,12 @@ fn codegen_global_asm_inner<'tcx>( let symbol = tcx.symbol_name(instance); global_asm.push_str(symbol.name); } + GlobalAsmOperandRef::ConstPointer { value: _ } => { + tcx.dcx().span_err( + span, + "asm! and global_asm! const pointer operands are not yet supported", + ); + } } } } diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 85cff9b5afad8..05a710fd013c3 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; -use gccjit::{LValue, RValue, ToRValue, Type}; +use gccjit::{GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -10,8 +10,8 @@ use rustc_codegen_ssa::traits::{ AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef, }; -use rustc_middle::bug; use rustc_middle::ty::Instance; +use rustc_middle::{bug, mir}; use rustc_span::Span; use rustc_target::asm::*; @@ -858,6 +858,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span], + instance: Instance<'tcx>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -865,6 +866,98 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let att_dialect = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) && options.contains(InlineAsmOptions::ATT_SYNTAX); + // Convert all operands to string interpolations + let converted_operands = operands + .iter() + .enumerate() + .map(|(operand_idx, operand)| { + match *operand { + GlobalAsmOperandRef::Interpolate { ref string } => { + // Const operands get injected directly into the + // template. Note that we don't need to escape $ + // here unlike normal inline assembly. + string.to_owned() + } + GlobalAsmOperandRef::ConstPointer { value } => { + let (prov, offset) = value.prov_and_relative_offset(); + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let symbol = 'sym: { + let alloc = match global_alloc { + mir::interpret::GlobalAlloc::Function { instance } => { + let function = get_fn(self, instance); + self.add_used_function(function); + // TODO(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O) + // or byte count suffixes (x86 Windows). + break 'sym self.tcx.symbol_name(instance).name.to_owned(); + } + mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => self + .tcx + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx + .instantiate_bound_regions_with_erased(principal) + }), + ))) + .unwrap_memory(), + mir::interpret::GlobalAlloc::Static(def_id) => { + // TODO(antoyo): set the global variable as used. + // TODO(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O). + let instance = Instance::mono(self.tcx, def_id); + break 'sym self.tcx.symbol_name(instance).name.to_owned(); + } + mir::interpret::GlobalAlloc::Memory(alloc) => alloc, + }; + + // For ZSTs directly codegen an aligned pointer. + if alloc.inner().len() == 0 { + assert_eq!(offset.bytes(), 0); + return format!("{}", alloc.inner().align.bytes()); + } + + let asm_name = self.tcx.symbol_name(instance); + let sym_name = format!("{asm_name}.{operand_idx}"); + + let init = crate::consts::const_alloc_to_gcc_uncached(self, alloc); + let alloc = alloc.inner(); + let typ = self.val_ty(init).get_aligned(alloc.align.bytes()); + + let global = self.declare_global_with_linkage( + &sym_name, + typ, + GlobalKind::Exported, + ); + global.global_set_initializer_rvalue(init); + // TODO(nbdd0121): set unnamed address. + // TODO(nbdd0121): set the global variable as used. + + sym_name + }; + + let offset = offset.bytes(); + if offset != 0 { format!("{symbol}+{offset}") } else { symbol } + } + GlobalAsmOperandRef::SymFn { instance } => { + let function = get_fn(self, instance); + self.add_used_function(function); + // TODO(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O) + // or byte count suffixes (x86 Windows). + self.tcx.symbol_name(instance).name.to_owned() + } + GlobalAsmOperandRef::SymStatic { def_id } => { + // TODO(antoyo): set the global variable as used. + // TODO(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O). + let instance = Instance::mono(self.tcx, def_id); + self.tcx.symbol_name(instance).name.to_owned() + } + } + }) + .collect::>(); + // Build the template string let mut template_str = ".pushsection .text\n".to_owned(); if att_dialect { @@ -888,33 +981,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } } InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { - match operands[operand_idx] { - GlobalAsmOperandRef::Interpolate { ref string } => { - // Const operands get injected directly into the - // template. Note that we don't need to escape % - // here unlike normal inline assembly. - template_str.push_str(string); - } - - GlobalAsmOperandRef::SymFn { instance } => { - let function = get_fn(self, instance); - self.add_used_function(function); - // TODO(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O) - // or byte count suffixes (x86 Windows). - let name = self.tcx.symbol_name(instance).name; - template_str.push_str(name); - } - - GlobalAsmOperandRef::SymStatic { def_id } => { - // TODO(antoyo): set the global variable as used. - // TODO(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O). - let instance = Instance::mono(self.tcx, def_id); - let name = self.tcx.symbol_name(instance).name; - template_str.push_str(name); - } - } + template_str.push_str(&converted_operands[operand_idx]); } } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index b1fcda68ffc56..60ddfb2e763f3 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -7,7 +7,7 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::{bug, span_bug}; +use rustc_middle::{bug, mir, span_bug}; use rustc_span::{Pos, Span, Symbol, sym}; use rustc_target::asm::*; use smallvec::SmallVec; @@ -389,6 +389,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span], + instance: Instance<'tcx>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -396,6 +397,111 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { let intel_syntax = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) && !options.contains(InlineAsmOptions::ATT_SYNTAX); + // Convert all operands to string interpolations + let converted_operands = operands + .iter() + .enumerate() + .map(|(operand_idx, operand)| { + match *operand { + GlobalAsmOperandRef::Interpolate { ref string } => { + // Const operands get injected directly into the + // template. Note that we don't need to escape $ + // here unlike normal inline assembly. + string.to_owned() + } + GlobalAsmOperandRef::ConstPointer { value } => { + let (prov, offset) = value.prov_and_relative_offset(); + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let llval = 'llval: { + let alloc = match global_alloc { + mir::interpret::GlobalAlloc::Function { instance } => { + break 'llval self.get_fn(instance); + } + mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => self + .tcx + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx + .instantiate_bound_regions_with_erased(principal) + }), + ))) + .unwrap_memory(), + mir::interpret::GlobalAlloc::Static(def_id) => { + break 'llval self + .renamed_statics + .borrow() + .get(&def_id) + .copied() + .unwrap_or_else(|| self.get_static(def_id)); + } + mir::interpret::GlobalAlloc::Memory(alloc) => alloc, + }; + + // For ZSTs directly codegen an aligned pointer. + if alloc.inner().len() == 0 { + assert_eq!(offset.bytes(), 0); + return format!("{}", alloc.inner().align.bytes()); + } + + let asm_name = self.tcx.symbol_name(instance); + let sym_name = format!("{asm_name}.{operand_idx}"); + + let init = crate::consts::const_alloc_to_llvm( + self, alloc, /*static*/ false, + ); + let alloc = alloc.inner(); + let g = self.static_addr_of_mut(init, alloc.align, None); + if alloc.mutability.is_not() { + // NB: we can't use `static_addr_of_impl` here to avoid sharing + // the global, as we need to set name and linkage. + unsafe { llvm::LLVMSetGlobalConstant(g, llvm::True) }; + } + + llvm::set_value_name(g, sym_name.as_bytes()); + + // `static_addr_of_mut` gives us a private global which can't be + // used by global asm. Update it to a hidden internal global instead. + llvm::set_linkage(g, llvm::Linkage::InternalLinkage); + llvm::set_visibility(g, llvm::Visibility::Hidden); + g + }; + self.add_compiler_used_global(llval); + let symbol = llvm::build_string(|s| unsafe { + llvm::LLVMRustGetMangledName(llval, s); + }) + .expect("symbol is not valid UTF-8"); + + let offset = offset.bytes(); + if offset != 0 { format!("{symbol}+{offset}") } else { symbol } + } + GlobalAsmOperandRef::SymFn { instance } => { + let llval = self.get_fn(instance); + self.add_compiler_used_global(llval); + let symbol = llvm::build_string(|s| unsafe { + llvm::LLVMRustGetMangledName(llval, s); + }) + .expect("symbol is not valid UTF-8"); + symbol + } + GlobalAsmOperandRef::SymStatic { def_id } => { + let llval = self + .renamed_statics + .borrow() + .get(&def_id) + .copied() + .unwrap_or_else(|| self.get_static(def_id)); + self.add_compiler_used_global(llval); + let symbol = llvm::build_string(|s| unsafe { + llvm::LLVMRustGetMangledName(llval, s); + }) + .expect("symbol is not valid UTF-8"); + symbol + } + } + }) + .collect::>(); + // Build the template string let mut template_str = String::new(); if intel_syntax { @@ -405,37 +511,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { - match operands[operand_idx] { - GlobalAsmOperandRef::Interpolate { ref string } => { - // Const operands get injected directly into the - // template. Note that we don't need to escape $ - // here unlike normal inline assembly. - template_str.push_str(string); - } - GlobalAsmOperandRef::SymFn { instance } => { - let llval = self.get_fn(instance); - self.add_compiler_used_global(llval); - let symbol = llvm::build_string(|s| unsafe { - llvm::LLVMRustGetMangledName(llval, s); - }) - .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); - } - GlobalAsmOperandRef::SymStatic { def_id } => { - let llval = self - .renamed_statics - .borrow() - .get(&def_id) - .copied() - .unwrap_or_else(|| self.get_static(def_id)); - self.add_compiler_used_global(llval); - let symbol = llvm::build_string(|s| unsafe { - llvm::LLVMRustGetMangledName(llval, s); - }) - .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); - } - } + template_str.push_str(&converted_operands[operand_idx]) } } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index da6d4e4c12cac..e3f4c1db91482 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -19,9 +19,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_middle::middle::exported_symbols::{self, SymbolExportKind}; use rustc_middle::middle::lang_items; -use rustc_middle::mir::BinOp; -use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir::interpret::{ErrorHandled, Scalar}; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions}; +use rustc_middle::mir::{BinOp, ConstValue}; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -409,13 +409,27 @@ where Ok(const_value) => { let ty = cx.tcx().typeck_body(anon_const.body).node_type(anon_const.hir_id); - let string = common::asm_const_to_str( - cx.tcx(), - *op_sp, - const_value, - cx.layout_of(ty), - ); - GlobalAsmOperandRef::Interpolate { string } + let ConstValue::Scalar(scalar) = const_value else { + span_bug!( + *op_sp, + "expected Scalar for promoted asm const, but got {:#?}", + const_value + ) + }; + match scalar { + Scalar::Int(_) => { + let string = common::asm_const_to_str( + cx.tcx(), + *op_sp, + const_value, + cx.layout_of(ty), + ); + GlobalAsmOperandRef::Interpolate { string } + } + Scalar::Ptr(value, _) => { + GlobalAsmOperandRef::ConstPointer { value } + } + } } Err(ErrorHandled::Reported { .. }) => { // An error has already been reported and @@ -457,7 +471,13 @@ where }) .collect(); - cx.codegen_global_asm(asm.template, &operands, asm.options, asm.line_spans); + cx.codegen_global_asm( + asm.template, + &operands, + asm.options, + asm.line_spans, + Instance::mono(cx.tcx(), item_id.owner_id.to_def_id()), + ); } else { span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type") } diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 48565e0b4de47..d9247fe2965c0 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -156,7 +156,7 @@ pub fn asm_const_to_str<'tcx>( }; let value = scalar.assert_scalar_int().to_bits(ty_and_layout.size); match ty_and_layout.ty.kind() { - ty::Uint(_) => value.to_string(), + ty::Uint(_) | ty::RawPtr(..) | ty::Ref(..) => value.to_string(), ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) { ty::IntTy::I8 => (value as i8).to_string(), ty::IntTy::I16 => (value as i16).to_string(), diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 73627405c1576..61397bda546f4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,10 +1,11 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; use rustc_attr_data_structures::InstructionSetAttr; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility}; -use rustc_middle::mir::{InlineAsmOperand, START_BLOCK}; +use rustc_middle::mir::{ConstValue, InlineAsmOperand, START_BLOCK}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::{bug, ty}; +use rustc_middle::{bug, span_bug, ty}; use rustc_span::sym; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::BinaryFormat; @@ -52,7 +53,7 @@ pub fn codegen_naked_asm< template_vec.extend(template.iter().cloned()); template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(end.into())); - cx.codegen_global_asm(&template_vec, &operands, options, line_spans); + cx.codegen_global_asm(&template_vec, &operands, options, line_spans, instance); } fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>>( @@ -77,14 +78,25 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL ty::EarlyBinder::bind(value.ty()), ); - let string = common::asm_const_to_str( - cx.tcx(), - value.span, - const_value, - cx.layout_of(mono_type), - ); - - GlobalAsmOperandRef::Interpolate { string } + let ConstValue::Scalar(scalar) = const_value else { + span_bug!( + value.span, + "expected Scalar for promoted asm const, but got {:#?}", + const_value + ) + }; + match scalar { + Scalar::Int(_) => { + let string = common::asm_const_to_str( + cx.tcx(), + value.span, + const_value, + cx.layout_of(mono_type), + ); + GlobalAsmOperandRef::Interpolate { string } + } + Scalar::Ptr(value, _) => GlobalAsmOperandRef::ConstPointer { value }, + } } InlineAsmOperand::SymFn { value } => { let mono_type = instance.instantiate_mir_and_normalize_erasing_regions( diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index 84319f2bcd281..5d9d76ae4fa65 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -1,5 +1,6 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::def_id::DefId; +use rustc_middle::mir; use rustc_middle::ty::Instance; use rustc_span::Span; use rustc_target::asm::InlineAsmRegOrRegClass; @@ -51,6 +52,7 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { #[derive(Debug)] pub enum GlobalAsmOperandRef<'tcx> { Interpolate { string: String }, + ConstPointer { value: mir::interpret::Pointer }, SymFn { instance: Instance<'tcx> }, SymStatic { def_id: DefId }, } @@ -70,12 +72,14 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { } pub trait AsmCodegenMethods<'tcx> { + /// Code generate a global or naked assembly. fn codegen_global_asm( &mut self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, line_spans: &[Span], + instance: Instance<'tcx>, ); /// The mangled name of this instance diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 68627a45b97b7..d5e4366d8dea3 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -494,8 +494,7 @@ fn collect_items_rec<'tcx>( Err(ErrorHandled::TooGeneric(..)) => { span_bug!(*op_sp, "asm const cannot be resolved; too generic") } - Err(err @ ErrorHandled::Reported(..)) => { - err.emit_note(tcx); + Err(ErrorHandled::Reported(..)) => { continue; } } diff --git a/tests/assembly/asm/global_asm.rs b/tests/assembly/asm/global_asm.rs index 8a4bf98c7450b..deb8d72f076b5 100644 --- a/tests/assembly/asm/global_asm.rs +++ b/tests/assembly/asm/global_asm.rs @@ -5,6 +5,7 @@ //@ compile-flags: -C symbol-mangling-version=v0 #![crate_type = "rlib"] +#![feature(asm_const_ptr)] use std::arch::global_asm; @@ -26,6 +27,10 @@ global_asm!("call {}", sym my_func); global_asm!("lea rax, [rip + {}]", sym MY_STATIC); // CHECK: call _RNvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_10global_asm6foobar global_asm!("call {}", sym foobar); +// CHECK: lea rax, [rip + _RNSC[[CRATE_IDENT]]_10global_asms4_10global_asm.0] +global_asm!("lea rax, [rip + {}]", const &1); +// CHECK: lea rax, [rip + _RNSC[[CRATE_IDENT]]_10global_asms5_10global_asm.0+4] +global_asm!("lea rax, [rip + {}]", const &[1; 2][1]); // CHECK: _RNvC[[CRATE_IDENT]]_10global_asm6foobar: fn foobar() { loop {} diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs index 6120ed0d53275..921dfc69b646a 100644 --- a/tests/assembly/asm/x86-types.rs +++ b/tests/assembly/asm/x86-types.rs @@ -9,7 +9,7 @@ //@ compile-flags: -C target-feature=+avx512bw //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, repr_simd, f16, f128)] +#![feature(no_core, repr_simd, f16, f128, asm_const_ptr)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -92,6 +92,18 @@ pub unsafe fn sym_fn() { asm!("call {}", sym extern_func); } +// NOTE: this only works for x64, as this test is compiled with PIC, +// and on x86 PIC symbol can't be constant. +// x86_64-LABEL: const_ptr: +// x86_64: #APP +// x86_64: mov al, byte ptr [{{.*}}anon{{.*}}] +// x86_64: #NO_APP +#[cfg(x86_64)] +#[no_mangle] +pub unsafe fn const_ptr() { + asm!("mov al, byte ptr [{}]", const &1); +} + // CHECK-LABEL: sym_static: // CHECK: #APP // CHECK: mov al, byte ptr [extern_static] diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs index e8f437196ec1c..218b49ecb8e1e 100644 --- a/tests/ui/asm/invalid-const-operand.rs +++ b/tests/ui/asm/invalid-const-operand.rs @@ -17,7 +17,7 @@ global_asm!("{}", const 0 as *mut u8); fn test1() { unsafe { - // Const operands must be integers and must be constants. + // Const operands must be integers or thin pointers asm!("{}", const 0); asm!("{}", const 0i32); @@ -25,8 +25,13 @@ fn test1() { asm!("{}", const 0f32); //~^ ERROR invalid type for `const` operand asm!("{}", const 0 as *mut u8); + asm!("{}", const &0); asm!("{}", const b"Foo".as_slice()); //~^ ERROR invalid type for `const` operand + + asm!("{}", const test1 as fn()); + asm!("{}", const test1); + //~^ ERROR invalid type for `const` operand } } diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr index d09571a49221a..c6b492788b0dc 100644 --- a/tests/ui/asm/invalid-const-operand.stderr +++ b/tests/ui/asm/invalid-const-operand.stderr @@ -1,5 +1,5 @@ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:44:26 + --> $DIR/invalid-const-operand.rs:49:26 | LL | asm!("{}", const x); | ^ non-constant value @@ -11,7 +11,7 @@ LL + const x: /* Type */ = 0; | error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:47:36 + --> $DIR/invalid-const-operand.rs:52:36 | LL | asm!("{}", const const_foo(x)); | ^ non-constant value @@ -23,7 +23,7 @@ LL + const x: /* Type */ = 0; | error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/invalid-const-operand.rs:50:36 + --> $DIR/invalid-const-operand.rs:55:36 | LL | asm!("{}", const const_bar(x)); | ^ non-constant value @@ -55,7 +55,7 @@ LL | asm!("{}", const 0f32); = help: `const` operands must be of an integer or thin pointer type error: invalid type for `const` operand - --> $DIR/invalid-const-operand.rs:28:20 + --> $DIR/invalid-const-operand.rs:29:20 | LL | asm!("{}", const b"Foo".as_slice()); | ^^^^^^----------------- @@ -64,6 +64,16 @@ LL | asm!("{}", const b"Foo".as_slice()); | = help: `const` operands must be of an integer or thin pointer type -error: aborting due to 6 previous errors +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:33:20 + | +LL | asm!("{}", const test1); + | ^^^^^^----- + | | + | is a `fn() {test1}` + | + = help: `const` operands must be of an integer or thin pointer type + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs b/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs index cc124ae39a399..cdcb5995a0f08 100644 --- a/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs +++ b/tests/ui/feature-gates/feature-gate-asm_const_ptr.rs @@ -1,8 +1,20 @@ //@ only-x86_64 -use std::arch::asm; +use std::arch::{asm, global_asm, naked_asm}; + +global_asm!("/* {} */", const &0); +//~^ ERROR using pointers in asm `const` operand is experimental + +#[unsafe(naked)] +extern "C" fn naked() { + unsafe { + naked_asm!("ret /* {} */", const &0); + //~^ ERROR using pointers in asm `const` operand is experimental + } +} fn main() { + naked(); unsafe { asm!("/* {} */", const &0); //~^ ERROR using pointers in asm `const` operand is experimental diff --git a/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr b/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr index 8cc21dd853b49..a804d8fe44be5 100644 --- a/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_const_ptr.stderr @@ -1,5 +1,25 @@ error[E0658]: using pointers in asm `const` operand is experimental - --> $DIR/feature-gate-asm_const_ptr.rs:7:26 + --> $DIR/feature-gate-asm_const_ptr.rs:5:25 + | +LL | global_asm!("/* {} */", const &0); + | ^^^^^^^^ + | + = note: see issue #128464 for more information + = help: add `#![feature(asm_const_ptr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: using pointers in asm `const` operand is experimental + --> $DIR/feature-gate-asm_const_ptr.rs:11:36 + | +LL | naked_asm!("ret /* {} */", const &0); + | ^^^^^^^^ + | + = note: see issue #128464 for more information + = help: add `#![feature(asm_const_ptr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: using pointers in asm `const` operand is experimental + --> $DIR/feature-gate-asm_const_ptr.rs:19:26 | LL | asm!("/* {} */", const &0); | ^^^^^^^^ @@ -8,6 +28,6 @@ LL | asm!("/* {} */", const &0); = help: add `#![feature(asm_const_ptr)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. From 3e675f4c5085df8ae19392e6de2caef7cb336f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 9 Jul 2025 22:25:03 +0200 Subject: [PATCH 30/36] Fix `--skip-std-check-if-no-download-rustc` Since https://github.com/rust-lang/rust/pull/143048, we now explicitly set the build compiler for `check::Std`, which caused it to be built before we checked `--skip-std-check-if-no-download-rustc`. So I moved the check earlier to `make_run`, which resolves it. I also added a regression test for this. Sadly we can't really test for the positive case easily (when download-ci-rustc is enabled), but we can test the negative cases, where it is disabled. --- src/bootstrap/src/core/build_steps/check.rs | 14 ++++++------ src/bootstrap/src/core/builder/tests.rs | 24 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 0497bae86a1c8..0cc4628310aba 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -47,6 +47,13 @@ impl Step for Std { } fn make_run(run: RunConfig<'_>) { + if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc { + eprintln!( + "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping." + ); + return; + } + let crates = std_crates_for_run_make(&run); run.builder.ensure(Std { build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std), @@ -56,13 +63,6 @@ impl Step for Std { } fn run(self, builder: &Builder<'_>) { - if !builder.download_rustc() && builder.config.skip_std_check_if_no_download_rustc { - eprintln!( - "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping." - ); - return; - } - let build_compiler = self.build_compiler; let stage = build_compiler.stage; let target = self.target; diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index bbcb58fca14f3..75cc5e01ec90f 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1439,6 +1439,30 @@ mod snapshot { "); } + /// Make sure that we don't check library when download-rustc is disabled + /// when `--skip-std-check-if-no-download-rustc` was passed. + #[test] + fn check_library_skip_without_download_rustc() { + let ctx = TestCtx::new(); + let args = ["--set", "rust.download-rustc=false", "--skip-std-check-if-no-download-rustc"]; + insta::assert_snapshot!( + ctx.config("check") + .paths(&["library"]) + .args(&args) + .render_steps(), @""); + + insta::assert_snapshot!( + ctx.config("check") + .paths(&["library", "compiler"]) + .args(&args) + .render_steps(), @r" + [build] llvm + [check] rustc 0 -> rustc 1 + [check] rustc 0 -> cranelift 1 + [check] rustc 0 -> gcc 1 + "); + } + #[test] fn check_miri_no_explicit_stage() { let ctx = TestCtx::new(); From 84eeca2e2fc40bb8d6641846f18af9d8fc6a9681 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Jul 2025 07:27:41 +0000 Subject: [PATCH 31/36] Make some "safe" llvm ops actually sound --- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_llvm/src/builder/autodiff.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 10 ++++++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index bde6a9cf4bc61..506286fc2559b 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1182,7 +1182,7 @@ fn create_msvc_imps( .filter_map(|val| { // Exclude some symbols that we know are not Rust symbols. let name = llvm::get_value_name(val); - if ignored(name) { None } else { Some((val, name)) } + if ignored(&name) { None } else { Some((val, name)) } }) .map(move |(val, name)| { let mut imp_name = prefix.as_bytes().to_vec(); diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index b07d9a5cfca8c..5afb9a60d4241 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -306,7 +306,7 @@ fn generate_enzyme_call<'ll>( // add outer_fn name to ad_name to make it unique, in case users apply autodiff to multiple // functions. Unwrap will only panic, if LLVM gave us an invalid string. let name = llvm::get_value_name(outer_fn); - let outer_fn_name = std::str::from_utf8(name).unwrap(); + let outer_fn_name = std::str::from_utf8(&name).unwrap(); ad_name.push_str(outer_fn_name); // Let us assume the user wrote the following function square: diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 28f5282c6b0d8..9c5008e03044a 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -430,7 +430,7 @@ impl<'ll> CodegenCx<'ll, '_> { // specific rules on what can be cast. So instead of adding a new way to // generate static initializers that match the static's type, we picked // the easier option and retroactively change the type of the static item itself. - let name = llvm::get_value_name(g).to_vec(); + let name = llvm::get_value_name(g); llvm::set_value_name(g, b""); let linkage = llvm::get_linkage(g); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 661174a80dfbd..3fc83fca352a8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -211,7 +211,7 @@ pub(crate) fn SetFunctionCallConv(fn_: &Value, cc: CallConv) { // function. // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52 pub(crate) fn SetUniqueComdat(llmod: &Module, val: &Value) { - let name_buf = get_value_name(val).to_vec(); + let name_buf = get_value_name(val); let name = CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap(); set_comdat(llmod, val, &name); @@ -319,12 +319,14 @@ pub(crate) fn get_param(llfn: &Value, index: c_uint) -> &Value { } } -/// Safe wrapper for `LLVMGetValueName2` into a byte slice -pub(crate) fn get_value_name(value: &Value) -> &[u8] { +/// Safe wrapper for `LLVMGetValueName2` +/// Needs to allocate the value, because `set_value_name` will invalidate +/// the pointer. +pub(crate) fn get_value_name(value: &Value) -> Vec { unsafe { let mut len = 0; let data = LLVMGetValueName2(value, &mut len); - std::slice::from_raw_parts(data.cast(), len) + std::slice::from_raw_parts(data.cast(), len).to_vec() } } From 7632c55abb307730a0ec461a9bd43dd05d1c0724 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 10 Jul 2025 14:07:12 +0200 Subject: [PATCH 32/36] extract single_import_can_define_name and finalize_glob_module_binding --- compiler/rustc_resolve/src/ident.rs | 261 +++++++++++++++------------- 1 file changed, 143 insertions(+), 118 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 68fbe48ebcb08..558cbef0014cc 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -13,7 +13,7 @@ use rustc_span::{Ident, Span, kw, sym}; use tracing::{debug, instrument}; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; -use crate::imports::Import; +use crate::imports::{Import, NameResolution}; use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ @@ -37,7 +37,7 @@ impl From for bool { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] enum Shadowing { Restricted, Unrestricted, @@ -879,53 +879,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .into_iter() .find_map(|binding| if binding == ignore_binding { None } else { binding }); - if let Some(Finalize { path_span, report_private, used, root_span, .. }) = finalize { - let Some(binding) = binding else { - return Err((Determined, Weak::No)); - }; - - if !self.is_accessible_from(binding.vis, parent_scope.module) { - if report_private { - self.privacy_errors.push(PrivacyError { - ident, - binding, - dedup_span: path_span, - outermost_res: None, - parent_scope: *parent_scope, - single_nested: path_span != root_span, - }); - } else { - return Err((Determined, Weak::No)); - } - } - - // Forbid expanded shadowing to avoid time travel. - if let Some(shadowed_glob) = resolution.shadowed_glob - && shadowing == Shadowing::Restricted - && binding.expansion != LocalExpnId::ROOT - && binding.res() != shadowed_glob.res() - { - self.ambiguity_errors.push(AmbiguityError { - kind: AmbiguityKind::GlobVsExpanded, - ident, - b1: binding, - b2: shadowed_glob, - warning: false, - misc1: AmbiguityErrorMisc::None, - misc2: AmbiguityErrorMisc::None, - }); - } - - if shadowing == Shadowing::Unrestricted - && binding.expansion != LocalExpnId::ROOT - && let NameBindingKind::Import { import, .. } = binding.kind - && matches!(import.kind, ImportKind::MacroExport) - { - self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); - } - - self.record_use(ident, binding, used); - return Ok(binding); + if let Some(finalize) = finalize { + return self.finalize_module_binding( + ident, + binding, + resolution.shadowed_glob, + parent_scope, + finalize, + shadowing, + ); } let check_usable = |this: &mut Self, binding: NameBinding<'ra>| { @@ -944,75 +906,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Check if one of single imports can still define the name, // if it can then our result is not determined and can be invalidated. - for single_import in &resolution.single_imports { - if ignore_import == Some(*single_import) { - // This branch handles a cycle in single imports. - // - // For example: - // ``` - // use a::b; - // use b as a; - // ``` - // 1. Record `use a::b` as the `ignore_import` and attempt to locate `a` in the - // current module. - // 2. Encounter the import `use b as a`, which is a `single_import` for `a`, - // and try to find `b` in the current module. - // 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`. - // This leads to entering this branch. - continue; - } - if !self.is_accessible_from(single_import.vis, parent_scope.module) { - continue; - } - if let Some(ignored) = ignore_binding - && let NameBindingKind::Import { import, .. } = ignored.kind - && import == *single_import - { - // Ignore not just the binding itself, but if it has a shadowed_glob, - // ignore that, too, because this loop is supposed to only process - // named imports. - continue; - } - - let Some(module) = single_import.imported_module.get() else { - return Err((Undetermined, Weak::No)); - }; - let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind - else { - unreachable!(); - }; - if source != target { - // This branch allows the binding to be defined or updated later if the target name - // can hide the source. - if target_bindings.iter().all(|binding| binding.get().is_none()) { - // None of the target bindings are available, so we can't determine - // if this binding is correct or not. - // See more details in #124840 - return Err((Undetermined, Weak::No)); - } else if target_bindings[ns].get().is_none() && binding.is_some() { - // `binding.is_some()` avoids the condition where the binding - // truly doesn't exist in this namespace and should return `Err(Determined)`. - return Err((Undetermined, Weak::No)); - } - } - - match self.resolve_ident_in_module( - module, - *source, - ns, - &single_import.parent_scope, - None, - ignore_binding, - ignore_import, - ) { - Err((Determined, _)) => continue, - Ok(binding) - if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) => - { - continue; - } - Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::No)), - } + if self.single_import_can_define_name( + &resolution, + binding, + ns, + ignore_import, + ignore_binding, + parent_scope, + ) { + return Err((Undetermined, Weak::No)); } // So we have a resolution that's from a glob import. This resolution is determined @@ -1101,6 +1003,129 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Err((Determined, Weak::No)) } + fn finalize_module_binding( + &mut self, + ident: Ident, + binding: Option>, + shadowed_glob: Option>, + parent_scope: &ParentScope<'ra>, + finalize: Finalize, + shadowing: Shadowing, + ) -> Result, (Determinacy, Weak)> { + let Finalize { path_span, report_private, used, root_span, .. } = finalize; + + let Some(binding) = binding else { + return Err((Determined, Weak::No)); + }; + + if !self.is_accessible_from(binding.vis, parent_scope.module) { + if report_private { + self.privacy_errors.push(PrivacyError { + ident, + binding, + dedup_span: path_span, + outermost_res: None, + parent_scope: *parent_scope, + single_nested: path_span != root_span, + }); + } else { + return Err((Determined, Weak::No)); + } + } + + // Forbid expanded shadowing to avoid time travel. + if let Some(shadowed_glob) = shadowed_glob + && shadowing == Shadowing::Restricted + && binding.expansion != LocalExpnId::ROOT + && binding.res() != shadowed_glob.res() + { + self.ambiguity_errors.push(AmbiguityError { + kind: AmbiguityKind::GlobVsExpanded, + ident, + b1: binding, + b2: shadowed_glob, + warning: false, + misc1: AmbiguityErrorMisc::None, + misc2: AmbiguityErrorMisc::None, + }); + } + + if shadowing == Shadowing::Unrestricted + && binding.expansion != LocalExpnId::ROOT + && let NameBindingKind::Import { import, .. } = binding.kind + && matches!(import.kind, ImportKind::MacroExport) + { + self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); + } + + self.record_use(ident, binding, used); + return Ok(binding); + } + + // Checks if a single import can define the `Ident` corresponding to `binding`. + // This is used to check whether we can definitively accept a glob as a resolution. + fn single_import_can_define_name( + &mut self, + resolution: &NameResolution<'ra>, + binding: Option>, + ns: Namespace, + ignore_import: Option>, + ignore_binding: Option>, + parent_scope: &ParentScope<'ra>, + ) -> bool { + for single_import in &resolution.single_imports { + if ignore_import == Some(*single_import) { + continue; + } + if !self.is_accessible_from(single_import.vis, parent_scope.module) { + continue; + } + if let Some(ignored) = ignore_binding + && let NameBindingKind::Import { import, .. } = ignored.kind + && import == *single_import + { + continue; + } + + let Some(module) = single_import.imported_module.get() else { + return true; + }; + let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind + else { + unreachable!(); + }; + if source != target { + if target_bindings.iter().all(|binding| binding.get().is_none()) { + return true; + } else if target_bindings[ns].get().is_none() && binding.is_some() { + return true; + } + } + + match self.resolve_ident_in_module( + module, + *source, + ns, + &single_import.parent_scope, + None, + ignore_binding, + ignore_import, + ) { + Err((Determined, _)) => continue, + Ok(binding) + if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) => + { + continue; + } + Ok(_) | Err((Undetermined, _)) => { + return true; + } + } + } + + false + } + /// Validate a local resolution (from ribs). #[instrument(level = "debug", skip(self, all_ribs))] fn validate_res_from_ribs( From 7dfc3e9af45ad54832c083baf0d2d0ca8e0d979a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Jul 2025 17:15:42 +0000 Subject: [PATCH 33/36] Rework borrowing suggestions to use `Expr` instead of just `Span` In the suggestion machinery for borrowing expressions and types, always use the available obligation `Span` to find the appropriate `Expr` to perform appropriateness checks no the `ExprKind` instead of on the textual snippet corresponding to the `Span`. Unify the logic for the case where `&` *and* `&mut` are appropriate with the logic for only one of those cases. Handle the case when `S::foo()` should have been `<&S>::foo()` (instead of suggesting the prior `&S::foo()`. --- .../src/error_reporting/traits/suggestions.rs | 228 ++++++++++-------- ...ize_of_val-align_of_val-extern-type.stderr | 20 +- tests/ui/derives/deriving-copyclone.stderr | 30 +-- .../ui/extern/unsized-extern-derefmove.stderr | 8 +- tests/ui/for/issue-20605.current.stderr | 9 +- tests/ui/for/issue-20605.next.stderr | 9 +- ...ry_self_types_generic_over_receiver.stderr | 16 +- .../imm-ref-trait-object-literal.stderr | 10 +- tests/ui/suggestions/issue-104961.stderr | 10 +- tests/ui/suggestions/issue-62843.stderr | 10 +- tests/ui/suggestions/issue-84973-2.stderr | 10 +- .../suggestions/issue-84973-negative.stderr | 10 +- tests/ui/suggestions/issue-84973.stderr | 10 +- ...dding-reference-to-trait-assoc-item.stderr | 20 +- ...ggest-imm-mut-trait-implementations.stderr | 20 +- .../negated-auto-traits-error.stderr | 10 +- 16 files changed, 217 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 3e64573aa0348..8c9eb41568f49 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1321,7 +1321,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref); let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref); - let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) = + let (ref_inner_ty_satisfies_pred, ref_inner_ty_is_mut) = if let ObligationCauseCode::WhereClauseInExpr(..) = obligation.cause.code() && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind() { @@ -1333,117 +1333,139 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (false, false) }; - if imm_ref_self_ty_satisfies_pred - || mut_ref_self_ty_satisfies_pred - || ref_inner_ty_satisfies_pred - { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - // We don't want a borrowing suggestion on the fields in structs, - // ``` - // struct Foo { - // the_foos: Vec - // } - // ``` - if !matches!( - span.ctxt().outer_expn_data().kind, - ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) - ) { - return false; - } - if snippet.starts_with('&') { - // This is already a literal borrow and the obligation is failing - // somewhere else in the obligation chain. Do not suggest non-sense. - return false; - } - // We have a very specific type of error, where just borrowing this argument - // might solve the problem. In cases like this, the important part is the - // original type obligation, not the last one that failed, which is arbitrary. - // Because of this, we modify the error to refer to the original obligation and - // return early in the caller. - - let msg = format!( - "the trait bound `{}` is not satisfied", - self.tcx.short_string(old_pred, err.long_ty_path()), - ); - let self_ty_str = - self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path()); - if has_custom_message { - err.note(msg); - } else { - err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)]; - } - err.span_label( - span, - format!( - "the trait `{}` is not implemented for `{self_ty_str}`", - old_pred.print_modifiers_and_trait_path() - ), - ); + let is_immut = imm_ref_self_ty_satisfies_pred + || (ref_inner_ty_satisfies_pred && !ref_inner_ty_is_mut); + let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_is_mut; + if !is_immut && !is_mut { + return false; + } + let Ok(_snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { + return false; + }; + // We don't want a borrowing suggestion on the fields in structs + // ``` + // #[derive(Clone)] + // struct Foo { + // the_foos: Vec + // } + // ``` + if !matches!( + span.ctxt().outer_expn_data().kind, + ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) + ) { + return false; + } + // We have a very specific type of error, where just borrowing this argument + // might solve the problem. In cases like this, the important part is the + // original type obligation, not the last one that failed, which is arbitrary. + // Because of this, we modify the error to refer to the original obligation and + // return early in the caller. - if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred { - err.span_suggestions( - span.shrink_to_lo(), - "consider borrowing here", - ["&".to_string(), "&mut ".to_string()], - Applicability::MaybeIncorrect, - ); - } else { - let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut; - let sugg_prefix = format!("&{}", if is_mut { "mut " } else { "" }); - let sugg_msg = format!( - "consider{} borrowing here", - if is_mut { " mutably" } else { "" } - ); + let mut label = || { + let msg = format!( + "the trait bound `{}` is not satisfied", + self.tcx.short_string(old_pred, err.long_ty_path()), + ); + let self_ty_str = + self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path()); + if has_custom_message { + err.note(msg); + } else { + err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)]; + } + err.span_label( + span, + format!( + "the trait `{}` is not implemented for `{self_ty_str}`", + old_pred.print_modifiers_and_trait_path() + ), + ); + }; - // Issue #109436, we need to add parentheses properly for method calls - // for example, `foo.into()` should be `(&foo).into()` - if let Some(_) = - self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50)) - { - err.multipart_suggestion_verbose( - sugg_msg, - vec![ - (span.shrink_to_lo(), format!("({sugg_prefix}")), - (span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MaybeIncorrect, - ); - return true; - } + let mut sugg_prefixes = vec![]; + if is_immut { + sugg_prefixes.push("&"); + } + if is_mut { + sugg_prefixes.push("&mut "); + } + let sugg_msg = format!( + "consider{} borrowing here", + if is_mut && !is_immut { " mutably" } else { "" }, + ); - // Issue #104961, we need to add parentheses properly for compound expressions - // for example, `x.starts_with("hi".to_string() + "you")` - // should be `x.starts_with(&("hi".to_string() + "you"))` - let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) - else { - return false; - }; - let mut expr_finder = FindExprBySpan::new(span, self.tcx); - expr_finder.visit_expr(body.value); - let Some(expr) = expr_finder.result else { - return false; - }; - let needs_parens = expr_needs_parens(expr); + // Issue #104961, we need to add parentheses properly for compound expressions + // for example, `x.starts_with("hi".to_string() + "you")` + // should be `x.starts_with(&("hi".to_string() + "you"))` + let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) else { + return false; + }; + let mut expr_finder = FindExprBySpan::new(span, self.tcx); + expr_finder.visit_expr(body.value); - let span = if needs_parens { span } else { span.shrink_to_lo() }; - let suggestions = if !needs_parens { - vec![(span.shrink_to_lo(), sugg_prefix)] - } else { + if let Some(ty) = expr_finder.ty_result { + if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(ty.hir_id) + && let hir::ExprKind::Path(hir::QPath::TypeRelative(_, _)) = expr.kind + && ty.span == span + { + // We've encountered something like `str::from("")`, where the intended code + // was likely `<&str>::from("")`. #143393. + label(); + err.multipart_suggestions( + sugg_msg, + sugg_prefixes.into_iter().map(|sugg_prefix| { vec![ - (span.shrink_to_lo(), format!("{sugg_prefix}(")), - (span.shrink_to_hi(), ")".to_string()), + (span.shrink_to_lo(), format!("<{sugg_prefix}")), + (span.shrink_to_hi(), ">".to_string()), ] - }; - err.multipart_suggestion_verbose( - sugg_msg, - suggestions, - Applicability::MaybeIncorrect, - ); - } + }), + Applicability::MaybeIncorrect, + ); return true; } + return false; } - return false; + let Some(expr) = expr_finder.result else { + return false; + }; + if let hir::ExprKind::AddrOf(_, _, _) = expr.kind { + return false; + } + let needs_parens_post = expr_needs_parens(expr); + let needs_parens_pre = match self.tcx.parent_hir_node(expr.hir_id) { + Node::Expr(e) + if let hir::ExprKind::MethodCall(_, base, _, _) = e.kind + && base.hir_id == expr.hir_id => + { + true + } + _ => false, + }; + + label(); + let suggestions = sugg_prefixes.into_iter().map(|sugg_prefix| { + match (needs_parens_pre, needs_parens_post) { + (false, false) => vec![(span.shrink_to_lo(), sugg_prefix.to_string())], + // We have something like `foo.bar()`, where we want to bororw foo, so we need + // to suggest `(&mut foo).bar()`. + (false, true) => vec![ + (span.shrink_to_lo(), format!("{sugg_prefix}(")), + (span.shrink_to_hi(), ")".to_string()), + ], + // Issue #109436, we need to add parentheses properly for method calls + // for example, `foo.into()` should be `(&foo).into()` + (true, false) => vec![ + (span.shrink_to_lo(), format!("({sugg_prefix}")), + (span.shrink_to_hi(), ")".to_string()), + ], + (true, true) => vec![ + (span.shrink_to_lo(), format!("({sugg_prefix}(")), + (span.shrink_to_hi(), "))".to_string()), + ], + } + }); + err.multipart_suggestions(sugg_msg, suggestions, Applicability::MaybeIncorrect); + return true; }; if let ObligationCauseCode::ImplDerived(cause) = &*code { diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index 6d6bc157771a4..825b9e941584c 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -2,25 +2,37 @@ error[E0277]: the size for values of type `Opaque` cannot be known --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:43 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; - | ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size + | ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque` | | | required by a bound introduced by this call | - = help: the trait `MetaSized` is not implemented for `Opaque` + = note: the trait bound `Opaque: MetaSized` is not satisfied note: required by a bound in `std::intrinsics::size_of_val` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL +help: consider borrowing here + | +LL | const _SIZE: usize = unsafe { size_of_val(&(&4 as *const i32 as *const Opaque)) }; + | ++ + +LL | const _SIZE: usize = unsafe { size_of_val(&mut (&4 as *const i32 as *const Opaque)) }; + | ++++++ + error[E0277]: the size for values of type `Opaque` cannot be known --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:45 | LL | const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; - | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque` | | | required by a bound introduced by this call | - = help: the trait `MetaSized` is not implemented for `Opaque` + = note: the trait bound `Opaque: MetaSized` is not satisfied note: required by a bound in `std::intrinsics::align_of_val` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL +help: consider borrowing here + | +LL | const _ALIGN: usize = unsafe { align_of_val(&(&4 as *const i32 as *const Opaque)) }; + | ++ + +LL | const _ALIGN: usize = unsafe { align_of_val(&mut (&4 as *const i32 as *const Opaque)) }; + | ++++++ + error: aborting due to 2 previous errors diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index befff8802804e..707a63ba28d2f 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -2,8 +2,10 @@ error[E0277]: the trait bound `B: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:31:26 | LL | is_copy(B { a: 1, b: C }); - | ------- ^ the trait `Copy` is not implemented for `B` - | | + | ------- ^ + | | | + | | the trait `Copy` is not implemented for `B` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | note: required for `B` to implement `Copy` @@ -16,17 +18,15 @@ note: required by a bound in `is_copy` | LL | fn is_copy(_: T) {} | ^^^^ required by this bound in `is_copy` -help: consider borrowing here - | -LL | is_copy(B { a: 1, b: &C }); - | + error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:27 | LL | is_clone(B { a: 1, b: C }); - | -------- ^ the trait `Clone` is not implemented for `B` - | | + | -------- ^ + | | | + | | the trait `Clone` is not implemented for `B` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | note: required for `B` to implement `Clone` @@ -39,17 +39,15 @@ note: required by a bound in `is_clone` | LL | fn is_clone(_: T) {} | ^^^^^ required by this bound in `is_clone` -help: consider borrowing here - | -LL | is_clone(B { a: 1, b: &C }); - | + error[E0277]: the trait bound `B: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:26 | LL | is_copy(B { a: 1, b: D }); - | ------- ^ the trait `Copy` is not implemented for `B` - | | + | ------- ^ + | | | + | | the trait `Copy` is not implemented for `B` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | note: required for `B` to implement `Copy` @@ -62,10 +60,6 @@ note: required by a bound in `is_copy` | LL | fn is_copy(_: T) {} | ^^^^ required by this bound in `is_copy` -help: consider borrowing here - | -LL | is_copy(B { a: 1, b: &D }); - | + error: aborting due to 3 previous errors diff --git a/tests/ui/extern/unsized-extern-derefmove.stderr b/tests/ui/extern/unsized-extern-derefmove.stderr index d6be76a9d6261..a9efc2e66e3b0 100644 --- a/tests/ui/extern/unsized-extern-derefmove.stderr +++ b/tests/ui/extern/unsized-extern-derefmove.stderr @@ -21,10 +21,10 @@ note: required by a bound in `Box::::from_raw` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL help: consider borrowing here | -LL | Box::from_raw(&0 as *mut _) - | + -LL | Box::from_raw(&mut 0 as *mut _) - | ++++ +LL | Box::from_raw(&(0 as *mut _)) + | ++ + +LL | Box::from_raw(&mut (0 as *mut _)) + | ++++++ + error[E0277]: the size for values of type `Device` cannot be known --> $DIR/unsized-extern-derefmove.rs:11:5 diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr index 1a66cb4146495..289dca289aeb5 100644 --- a/tests/ui/for/issue-20605.current.stderr +++ b/tests/ui/for/issue-20605.current.stderr @@ -2,14 +2,13 @@ error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:6:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | -^^^^^^ + | | + | the trait `IntoIterator` is not implemented for `dyn Iterator` + | help: consider mutably borrowing here: `&mut` | = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required for `dyn Iterator` to implement `IntoIterator` -help: consider mutably borrowing here - | -LL | for item in &mut *things { *item = 0 } - | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 1a66cb4146495..289dca289aeb5 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -2,14 +2,13 @@ error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:6:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | -^^^^^^ + | | + | the trait `IntoIterator` is not implemented for `dyn Iterator` + | help: consider mutably borrowing here: `&mut` | = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required for `dyn Iterator` to implement `IntoIterator` -help: consider mutably borrowing here - | -LL | for item in &mut *things { *item = 0 } - | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr index 2da3925341e2f..7a3d8b43c2e3a 100644 --- a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr +++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr @@ -30,10 +30,10 @@ LL | fn a(self: impl Receiver) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::a` help: consider borrowing here | -LL | &foo.a(); - | + -LL | &mut foo.a(); - | ++++ +LL | (&foo).a(); + | ++ + +LL | (&mut foo).a(); + | +++++ + error[E0277]: the trait bound `Foo: Deref` is not satisfied --> $DIR/arbitrary_self_types_generic_over_receiver.rs:21:9 @@ -48,10 +48,10 @@ LL | fn b(self: impl Deref) -> u32 { | ^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::b` help: consider borrowing here | -LL | &foo.b(); - | + -LL | &mut foo.b(); - | ++++ +LL | (&foo).b(); + | ++ + +LL | (&mut foo).b(); + | +++++ + error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr index 4b770d572c565..62f1c03e9aaae 100644 --- a/tests/ui/suggestions/imm-ref-trait-object-literal.stderr +++ b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -21,8 +21,10 @@ error[E0277]: the trait bound `S: Trait` is not satisfied --> $DIR/imm-ref-trait-object-literal.rs:13:7 | LL | foo(s); - | --- ^ the trait `Trait` is not implemented for `S` - | | + | --- ^ + | | | + | | the trait `Trait` is not implemented for `S` + | | help: consider mutably borrowing here: `&mut` | required by a bound introduced by this call | note: required by a bound in `foo` @@ -30,10 +32,6 @@ note: required by a bound in `foo` | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` -help: consider mutably borrowing here - | -LL | foo(&mut s); - | ++++ error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-104961.stderr b/tests/ui/suggestions/issue-104961.stderr index 0d229e6dada5f..6f02c125cadf3 100644 --- a/tests/ui/suggestions/issue-104961.stderr +++ b/tests/ui/suggestions/issue-104961.stderr @@ -18,17 +18,15 @@ error[E0277]: the trait bound `String: Pattern` is not satisfied --> $DIR/issue-104961.rs:9:19 | LL | x.starts_with("hi".to_string()) - | ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern` is not implemented for `String` - | | + | ----------- -^^^^^^^^^^^^^^^ + | | | + | | the trait `Pattern` is not implemented for `String` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | = note: required for `String` to implement `Pattern` note: required by a bound in `core::str::::starts_with` --> $SRC_DIR/core/src/str/mod.rs:LL:COL -help: consider borrowing here - | -LL | x.starts_with(&"hi".to_string()) - | + error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr index c3c0360b3a9d1..c3480a8e396e8 100644 --- a/tests/ui/suggestions/issue-62843.stderr +++ b/tests/ui/suggestions/issue-62843.stderr @@ -2,17 +2,15 @@ error[E0277]: the trait bound `String: Pattern` is not satisfied --> $DIR/issue-62843.rs:4:32 | LL | println!("{:?}", line.find(pattern)); - | ---- ^^^^^^^ the trait `Pattern` is not implemented for `String` - | | + | ---- -^^^^^^ + | | | + | | the trait `Pattern` is not implemented for `String` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | = note: required for `String` to implement `Pattern` note: required by a bound in `core::str::::find` --> $SRC_DIR/core/src/str/mod.rs:LL:COL -help: consider borrowing here - | -LL | println!("{:?}", line.find(&pattern)); - | + error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-84973-2.stderr b/tests/ui/suggestions/issue-84973-2.stderr index 74995a0500acd..914307008efca 100644 --- a/tests/ui/suggestions/issue-84973-2.stderr +++ b/tests/ui/suggestions/issue-84973-2.stderr @@ -2,8 +2,10 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied --> $DIR/issue-84973-2.rs:11:9 | LL | foo(a); - | --- ^ the trait `Tr` is not implemented for `i32` - | | + | --- ^ + | | | + | | the trait `Tr` is not implemented for `i32` + | | help: consider mutably borrowing here: `&mut` | required by a bound introduced by this call | note: required by a bound in `foo` @@ -11,10 +13,6 @@ note: required by a bound in `foo` | LL | fn foo(i: T) {} | ^^ required by this bound in `foo` -help: consider mutably borrowing here - | -LL | foo(&mut a); - | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-84973-negative.stderr b/tests/ui/suggestions/issue-84973-negative.stderr index ce838bce09e7b..e3e6296890ff7 100644 --- a/tests/ui/suggestions/issue-84973-negative.stderr +++ b/tests/ui/suggestions/issue-84973-negative.stderr @@ -17,8 +17,10 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied --> $DIR/issue-84973-negative.rs:11:9 | LL | bar(b); - | --- ^ the trait `Tr` is not implemented for `f32` - | | + | --- ^ + | | | + | | the trait `Tr` is not implemented for `f32` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | note: required by a bound in `bar` @@ -26,10 +28,6 @@ note: required by a bound in `bar` | LL | fn bar(t: T) {} | ^^ required by this bound in `bar` -help: consider borrowing here - | -LL | bar(&b); - | + error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr index c5e1958e030f2..5ca91c544dbda 100644 --- a/tests/ui/suggestions/issue-84973.stderr +++ b/tests/ui/suggestions/issue-84973.stderr @@ -2,8 +2,10 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied --> $DIR/issue-84973.rs:6:24 | LL | let o = Other::new(f); - | ---------- ^ the trait `SomeTrait` is not implemented for `Fancy` - | | + | ---------- ^ + | | | + | | the trait `SomeTrait` is not implemented for `Fancy` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | note: required by a bound in `Other::<'a, G>::new` @@ -14,10 +16,6 @@ LL | G: SomeTrait, LL | { LL | pub fn new(g: G) -> Self { | --- required by a bound in this associated function -help: consider borrowing here - | -LL | let o = Other::new(&f); - | + error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr index 485015a98f2a7..146d6705243a6 100644 --- a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr @@ -2,23 +2,19 @@ error[E0277]: the trait bound `&mut usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9 | LL | foo(Default::default()); - | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` - | -help: consider mutably borrowing here - | -LL | foo(&mut Default::default()); - | ++++ + | -^^^^^^^^^^^^^^^^^ + | | + | the trait `Default` is not implemented for `&mut usize` + | help: consider mutably borrowing here: `&mut` error[E0277]: the trait bound `&usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9 | LL | bar(Default::default()); - | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` - | -help: consider borrowing here - | -LL | bar(&Default::default()); - | + + | -^^^^^^^^^^^^^^^^^ + | | + | the trait `Default` is not implemented for `&usize` + | help: consider borrowing here: `&` error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr index f2eb651eaa426..b3a0c68450e61 100644 --- a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr +++ b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr @@ -22,8 +22,10 @@ error[E0277]: the trait bound `B: Trait` is not satisfied --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9 | LL | foo(b); - | --- ^ the trait `Trait` is not implemented for `B` - | | + | --- ^ + | | | + | | the trait `Trait` is not implemented for `B` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | note: required by a bound in `foo` @@ -31,17 +33,15 @@ note: required by a bound in `foo` | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` -help: consider borrowing here - | -LL | foo(&b); - | + error[E0277]: the trait bound `C: Trait` is not satisfied --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9 | LL | foo(c); - | --- ^ the trait `Trait` is not implemented for `C` - | | + | --- ^ + | | | + | | the trait `Trait` is not implemented for `C` + | | help: consider mutably borrowing here: `&mut` | required by a bound introduced by this call | note: required by a bound in `foo` @@ -49,10 +49,6 @@ note: required by a bound in `foo` | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` -help: consider mutably borrowing here - | -LL | foo(&mut c); - | ++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index 8f5b937e586ae..cc5ca471788d9 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -61,8 +61,10 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:48:13 | LL | is_send(Box::new(TestType)); - | ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique` - | | + | ------- -^^^^^^^^^^^^^^^^^ + | | | + | | the trait `Send` is not implemented for `Unique` + | | help: consider borrowing here: `&` | required by a bound introduced by this call | = note: the trait bound `Unique: Send` is not satisfied @@ -74,10 +76,6 @@ note: required by a bound in `is_send` | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` -help: consider borrowing here - | -LL | is_send(&Box::new(TestType)); - | + error[E0277]: `dummy3::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:56:13 From 0674eca2f0c4ac45b7cf1a66fd4df44dfc603e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Jul 2025 17:21:59 +0000 Subject: [PATCH 34/36] Make `Diag::multipart_suggestions` always verbose --- compiler/rustc_errors/src/diagnostic.rs | 2 +- tests/ui/derives/deriving-copyclone.stderr | 30 +++++++++++-------- tests/ui/for/issue-20605.current.stderr | 9 +++--- tests/ui/for/issue-20605.next.stderr | 9 +++--- .../in-trait/default-body-type-err-2.stderr | 9 ++++-- tests/ui/inference/deref-suggestion.stderr | 9 ++++-- .../typo-in-repeat-expr-issue-80173.stderr | 9 ++++-- tests/ui/static/bad-const-type.stderr | 9 ++++-- .../imm-ref-trait-object-literal.stderr | 10 ++++--- tests/ui/suggestions/issue-104961.stderr | 10 ++++--- tests/ui/suggestions/issue-52820.stderr | 11 ++++--- tests/ui/suggestions/issue-53692.stderr | 23 +++++++++----- tests/ui/suggestions/issue-59819.stderr | 10 +++++-- tests/ui/suggestions/issue-62843.stderr | 10 ++++--- tests/ui/suggestions/issue-83943.stderr | 9 ++++-- tests/ui/suggestions/issue-84973-2.stderr | 10 ++++--- .../suggestions/issue-84973-negative.stderr | 10 ++++--- tests/ui/suggestions/issue-84973.stderr | 10 ++++--- ...-removal-of-conversion-method-calls.stderr | 9 ++++-- ...dding-reference-to-trait-assoc-item.stderr | 20 ++++++++----- ...ggest-imm-mut-trait-implementations.stderr | 20 ++++++++----- tests/ui/switched-expectations.stderr | 9 ++++-- .../negated-auto-traits-error.stderr | 10 ++++--- tests/ui/typeck/conversion-methods.stderr | 30 +++++++++++++------ 24 files changed, 187 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 5746c28a2ab26..a128f8d31a134 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1165,7 +1165,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.push_suggestion(CodeSuggestion { substitutions, msg: self.subdiagnostic_message_to_diagnostic_message(msg), - style: SuggestionStyle::ShowCode, + style: SuggestionStyle::ShowAlways, applicability, }); self diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 707a63ba28d2f..befff8802804e 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -2,10 +2,8 @@ error[E0277]: the trait bound `B: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:31:26 | LL | is_copy(B { a: 1, b: C }); - | ------- ^ - | | | - | | the trait `Copy` is not implemented for `B` - | | help: consider borrowing here: `&` + | ------- ^ the trait `Copy` is not implemented for `B` + | | | required by a bound introduced by this call | note: required for `B` to implement `Copy` @@ -18,15 +16,17 @@ note: required by a bound in `is_copy` | LL | fn is_copy(_: T) {} | ^^^^ required by this bound in `is_copy` +help: consider borrowing here + | +LL | is_copy(B { a: 1, b: &C }); + | + error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:27 | LL | is_clone(B { a: 1, b: C }); - | -------- ^ - | | | - | | the trait `Clone` is not implemented for `B` - | | help: consider borrowing here: `&` + | -------- ^ the trait `Clone` is not implemented for `B` + | | | required by a bound introduced by this call | note: required for `B` to implement `Clone` @@ -39,15 +39,17 @@ note: required by a bound in `is_clone` | LL | fn is_clone(_: T) {} | ^^^^^ required by this bound in `is_clone` +help: consider borrowing here + | +LL | is_clone(B { a: 1, b: &C }); + | + error[E0277]: the trait bound `B: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:26 | LL | is_copy(B { a: 1, b: D }); - | ------- ^ - | | | - | | the trait `Copy` is not implemented for `B` - | | help: consider borrowing here: `&` + | ------- ^ the trait `Copy` is not implemented for `B` + | | | required by a bound introduced by this call | note: required for `B` to implement `Copy` @@ -60,6 +62,10 @@ note: required by a bound in `is_copy` | LL | fn is_copy(_: T) {} | ^^^^ required by this bound in `is_copy` +help: consider borrowing here + | +LL | is_copy(B { a: 1, b: &D }); + | + error: aborting due to 3 previous errors diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr index 289dca289aeb5..1a66cb4146495 100644 --- a/tests/ui/for/issue-20605.current.stderr +++ b/tests/ui/for/issue-20605.current.stderr @@ -2,13 +2,14 @@ error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:6:17 | LL | for item in *things { *item = 0 } - | -^^^^^^ - | | - | the trait `IntoIterator` is not implemented for `dyn Iterator` - | help: consider mutably borrowing here: `&mut` + | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` | = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required for `dyn Iterator` to implement `IntoIterator` +help: consider mutably borrowing here + | +LL | for item in &mut *things { *item = 0 } + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 289dca289aeb5..1a66cb4146495 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -2,13 +2,14 @@ error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:6:17 | LL | for item in *things { *item = 0 } - | -^^^^^^ - | | - | the trait `IntoIterator` is not implemented for `dyn Iterator` - | help: consider mutably borrowing here: `&mut` + | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` | = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required for `dyn Iterator` to implement `IntoIterator` +help: consider mutably borrowing here + | +LL | for item in &mut *things { *item = 0 } + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr index 856c92217b924..4c429624e0bfa 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -4,9 +4,12 @@ error[E0308]: mismatched types LL | async fn woopsie_async(&self) -> String { | ------ expected `String` because of return type LL | 42 - | ^^- help: try using a conversion method: `.to_string()` - | | - | expected `String`, found integer + | ^^ expected `String`, found integer + | +help: try using a conversion method + | +LL | 42.to_string() + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr index 8ccd28198afc4..027902a9f31e2 100644 --- a/tests/ui/inference/deref-suggestion.stderr +++ b/tests/ui/inference/deref-suggestion.stderr @@ -2,9 +2,8 @@ error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:8:9 | LL | foo(s); - | --- ^- help: try using a conversion method: `.to_string()` - | | | - | | expected `String`, found `&String` + | --- ^ expected `String`, found `&String` + | | | arguments to this function are incorrect | note: function defined here @@ -12,6 +11,10 @@ note: function defined here | LL | fn foo(_: String) {} | ^^^ --------- +help: try using a conversion method + | +LL | foo(s.to_string()); + | ++++++++++++ error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:14:10 diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr index ce2022374f7f4..9f31a731fed72 100644 --- a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr +++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr @@ -38,9 +38,12 @@ error[E0308]: mismatched types --> $DIR/typo-in-repeat-expr-issue-80173.rs:32:29 | LL | let e = [String::new(), 10]; - | ^^- help: try using a conversion method: `.to_string()` - | | - | expected `String`, found integer + | ^^ expected `String`, found integer + | +help: try using a conversion method + | +LL | let e = [String::new(), 10.to_string()]; + | ++++++++++++ error[E0308]: mismatched types --> $DIR/typo-in-repeat-expr-issue-80173.rs:36:19 diff --git a/tests/ui/static/bad-const-type.stderr b/tests/ui/static/bad-const-type.stderr index 807cd2f7a25a7..8573a11ef2912 100644 --- a/tests/ui/static/bad-const-type.stderr +++ b/tests/ui/static/bad-const-type.stderr @@ -2,9 +2,12 @@ error[E0308]: mismatched types --> $DIR/bad-const-type.rs:1:20 | LL | static i: String = 10; - | ^^- help: try using a conversion method: `.to_string()` - | | - | expected `String`, found integer + | ^^ expected `String`, found integer + | +help: try using a conversion method + | +LL | static i: String = 10.to_string(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr index 62f1c03e9aaae..4b770d572c565 100644 --- a/tests/ui/suggestions/imm-ref-trait-object-literal.stderr +++ b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -21,10 +21,8 @@ error[E0277]: the trait bound `S: Trait` is not satisfied --> $DIR/imm-ref-trait-object-literal.rs:13:7 | LL | foo(s); - | --- ^ - | | | - | | the trait `Trait` is not implemented for `S` - | | help: consider mutably borrowing here: `&mut` + | --- ^ the trait `Trait` is not implemented for `S` + | | | required by a bound introduced by this call | note: required by a bound in `foo` @@ -32,6 +30,10 @@ note: required by a bound in `foo` | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut s); + | ++++ error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-104961.stderr b/tests/ui/suggestions/issue-104961.stderr index 6f02c125cadf3..0d229e6dada5f 100644 --- a/tests/ui/suggestions/issue-104961.stderr +++ b/tests/ui/suggestions/issue-104961.stderr @@ -18,15 +18,17 @@ error[E0277]: the trait bound `String: Pattern` is not satisfied --> $DIR/issue-104961.rs:9:19 | LL | x.starts_with("hi".to_string()) - | ----------- -^^^^^^^^^^^^^^^ - | | | - | | the trait `Pattern` is not implemented for `String` - | | help: consider borrowing here: `&` + | ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern` is not implemented for `String` + | | | required by a bound introduced by this call | = note: required for `String` to implement `Pattern` note: required by a bound in `core::str::::starts_with` --> $SRC_DIR/core/src/str/mod.rs:LL:COL +help: consider borrowing here + | +LL | x.starts_with(&"hi".to_string()) + | + error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-52820.stderr b/tests/ui/suggestions/issue-52820.stderr index a67d75014171f..de2c9542f6113 100644 --- a/tests/ui/suggestions/issue-52820.stderr +++ b/tests/ui/suggestions/issue-52820.stderr @@ -13,10 +13,13 @@ error[E0308]: mismatched types --> $DIR/issue-52820.rs:13:17 | LL | brains: guts.clone(), - | ^^^^^-----^^ - | | | - | | help: try using a conversion method: `to_string` - | expected `String`, found `&str` + | ^^^^^^^^^^^^ expected `String`, found `&str` + | +help: try using a conversion method + | +LL - brains: guts.clone(), +LL + brains: guts.to_string(), + | error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-53692.stderr b/tests/ui/suggestions/issue-53692.stderr index 469a538411fb1..10ebb30a5b24a 100644 --- a/tests/ui/suggestions/issue-53692.stderr +++ b/tests/ui/suggestions/issue-53692.stderr @@ -2,24 +2,31 @@ error[E0308]: mismatched types --> $DIR/issue-53692.rs:7:33 | LL | let items_clone: Vec = ref_items.clone(); - | -------- ^^^^^^^^^^-----^^ - | | | | - | | | help: try using a conversion method: `to_vec` - | | expected `Vec`, found `&[i32]` + | -------- ^^^^^^^^^^^^^^^^^ expected `Vec`, found `&[i32]` + | | | expected due to this | = note: expected struct `Vec` found reference `&[i32]` +help: try using a conversion method + | +LL - let items_clone: Vec = ref_items.clone(); +LL + let items_clone: Vec = ref_items.to_vec(); + | error[E0308]: mismatched types --> $DIR/issue-53692.rs:14:26 | LL | let string: String = s.clone(); - | ------ ^^-----^^ - | | | | - | | | help: try using a conversion method: `to_string` - | | expected `String`, found `&str` + | ------ ^^^^^^^^^ expected `String`, found `&str` + | | | expected due to this + | +help: try using a conversion method + | +LL - let string: String = s.clone(); +LL + let string: String = s.to_string(); + | error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-59819.stderr b/tests/ui/suggestions/issue-59819.stderr index 43acf9549c29a..ab91961192ff5 100644 --- a/tests/ui/suggestions/issue-59819.stderr +++ b/tests/ui/suggestions/issue-59819.stderr @@ -28,10 +28,14 @@ error[E0308]: mismatched types --> $DIR/issue-59819.rs:34:21 | LL | let g: String = f; - | ------ ^- help: try using a conversion method: `.to_string()` - | | | - | | expected `String`, found `Bar` + | ------ ^ expected `String`, found `Bar` + | | | expected due to this + | +help: try using a conversion method + | +LL | let g: String = f.to_string(); + | ++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr index c3480a8e396e8..c3c0360b3a9d1 100644 --- a/tests/ui/suggestions/issue-62843.stderr +++ b/tests/ui/suggestions/issue-62843.stderr @@ -2,15 +2,17 @@ error[E0277]: the trait bound `String: Pattern` is not satisfied --> $DIR/issue-62843.rs:4:32 | LL | println!("{:?}", line.find(pattern)); - | ---- -^^^^^^ - | | | - | | the trait `Pattern` is not implemented for `String` - | | help: consider borrowing here: `&` + | ---- ^^^^^^^ the trait `Pattern` is not implemented for `String` + | | | required by a bound introduced by this call | = note: required for `String` to implement `Pattern` note: required by a bound in `core::str::::find` --> $SRC_DIR/core/src/str/mod.rs:LL:COL +help: consider borrowing here + | +LL | println!("{:?}", line.find(&pattern)); + | + error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-83943.stderr b/tests/ui/suggestions/issue-83943.stderr index 1a085368485cf..e714a126f4a69 100644 --- a/tests/ui/suggestions/issue-83943.stderr +++ b/tests/ui/suggestions/issue-83943.stderr @@ -6,11 +6,14 @@ LL | | "A".to_string() | | --------------- expected because of this LL | | } else { LL | | "B" - | | ^^^- help: try using a conversion method: `.to_string()` - | | | - | | expected `String`, found `&str` + | | ^^^ expected `String`, found `&str` LL | | }; | |_____- `if` and `else` have incompatible types + | +help: try using a conversion method + | +LL | "B".to_string() + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-84973-2.stderr b/tests/ui/suggestions/issue-84973-2.stderr index 914307008efca..74995a0500acd 100644 --- a/tests/ui/suggestions/issue-84973-2.stderr +++ b/tests/ui/suggestions/issue-84973-2.stderr @@ -2,10 +2,8 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied --> $DIR/issue-84973-2.rs:11:9 | LL | foo(a); - | --- ^ - | | | - | | the trait `Tr` is not implemented for `i32` - | | help: consider mutably borrowing here: `&mut` + | --- ^ the trait `Tr` is not implemented for `i32` + | | | required by a bound introduced by this call | note: required by a bound in `foo` @@ -13,6 +11,10 @@ note: required by a bound in `foo` | LL | fn foo(i: T) {} | ^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut a); + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-84973-negative.stderr b/tests/ui/suggestions/issue-84973-negative.stderr index e3e6296890ff7..ce838bce09e7b 100644 --- a/tests/ui/suggestions/issue-84973-negative.stderr +++ b/tests/ui/suggestions/issue-84973-negative.stderr @@ -17,10 +17,8 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied --> $DIR/issue-84973-negative.rs:11:9 | LL | bar(b); - | --- ^ - | | | - | | the trait `Tr` is not implemented for `f32` - | | help: consider borrowing here: `&` + | --- ^ the trait `Tr` is not implemented for `f32` + | | | required by a bound introduced by this call | note: required by a bound in `bar` @@ -28,6 +26,10 @@ note: required by a bound in `bar` | LL | fn bar(t: T) {} | ^^ required by this bound in `bar` +help: consider borrowing here + | +LL | bar(&b); + | + error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr index 5ca91c544dbda..c5e1958e030f2 100644 --- a/tests/ui/suggestions/issue-84973.stderr +++ b/tests/ui/suggestions/issue-84973.stderr @@ -2,10 +2,8 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied --> $DIR/issue-84973.rs:6:24 | LL | let o = Other::new(f); - | ---------- ^ - | | | - | | the trait `SomeTrait` is not implemented for `Fancy` - | | help: consider borrowing here: `&` + | ---------- ^ the trait `SomeTrait` is not implemented for `Fancy` + | | | required by a bound introduced by this call | note: required by a bound in `Other::<'a, G>::new` @@ -16,6 +14,10 @@ LL | G: SomeTrait, LL | { LL | pub fn new(g: G) -> Self { | --- required by a bound in this associated function +help: consider borrowing here + | +LL | let o = Other::new(&f); + | + error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr index c721ceb11463f..ed94ebd27ffdf 100644 --- a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr @@ -5,9 +5,12 @@ LL | fn get_name() -> String { | ------ expected `String` because of return type ... LL | your_name.trim() - | ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` - | | - | expected `String`, found `&str` + | ^^^^^^^^^^^^^^^^ expected `String`, found `&str` + | +help: try using a conversion method + | +LL | your_name.trim().to_string() + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr index 146d6705243a6..485015a98f2a7 100644 --- a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr @@ -2,19 +2,23 @@ error[E0277]: the trait bound `&mut usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9 | LL | foo(Default::default()); - | -^^^^^^^^^^^^^^^^^ - | | - | the trait `Default` is not implemented for `&mut usize` - | help: consider mutably borrowing here: `&mut` + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` + | +help: consider mutably borrowing here + | +LL | foo(&mut Default::default()); + | ++++ error[E0277]: the trait bound `&usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9 | LL | bar(Default::default()); - | -^^^^^^^^^^^^^^^^^ - | | - | the trait `Default` is not implemented for `&usize` - | help: consider borrowing here: `&` + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` + | +help: consider borrowing here + | +LL | bar(&Default::default()); + | + error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr index b3a0c68450e61..f2eb651eaa426 100644 --- a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr +++ b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr @@ -22,10 +22,8 @@ error[E0277]: the trait bound `B: Trait` is not satisfied --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9 | LL | foo(b); - | --- ^ - | | | - | | the trait `Trait` is not implemented for `B` - | | help: consider borrowing here: `&` + | --- ^ the trait `Trait` is not implemented for `B` + | | | required by a bound introduced by this call | note: required by a bound in `foo` @@ -33,15 +31,17 @@ note: required by a bound in `foo` | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&b); + | + error[E0277]: the trait bound `C: Trait` is not satisfied --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9 | LL | foo(c); - | --- ^ - | | | - | | the trait `Trait` is not implemented for `C` - | | help: consider mutably borrowing here: `&mut` + | --- ^ the trait `Trait` is not implemented for `C` + | | | required by a bound introduced by this call | note: required by a bound in `foo` @@ -49,6 +49,10 @@ note: required by a bound in `foo` | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut c); + | ++++ error: aborting due to 3 previous errors diff --git a/tests/ui/switched-expectations.stderr b/tests/ui/switched-expectations.stderr index cc57674740020..e235c2da1f736 100644 --- a/tests/ui/switched-expectations.stderr +++ b/tests/ui/switched-expectations.stderr @@ -2,9 +2,12 @@ error[E0308]: mismatched types --> $DIR/switched-expectations.rs:3:30 | LL | let ref string: String = var; - | ^^^- help: try using a conversion method: `.to_string()` - | | - | expected `String`, found `i32` + | ^^^ expected `String`, found `i32` + | +help: try using a conversion method + | +LL | let ref string: String = var.to_string(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index cc5ca471788d9..8f5b937e586ae 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -61,10 +61,8 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:48:13 | LL | is_send(Box::new(TestType)); - | ------- -^^^^^^^^^^^^^^^^^ - | | | - | | the trait `Send` is not implemented for `Unique` - | | help: consider borrowing here: `&` + | ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique` + | | | required by a bound introduced by this call | = note: the trait bound `Unique: Send` is not satisfied @@ -76,6 +74,10 @@ note: required by a bound in `is_send` | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` +help: consider borrowing here + | +LL | is_send(&Box::new(TestType)); + | + error[E0277]: `dummy3::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:56:13 diff --git a/tests/ui/typeck/conversion-methods.stderr b/tests/ui/typeck/conversion-methods.stderr index a9b5078ccdde3..fa8928f1454c0 100644 --- a/tests/ui/typeck/conversion-methods.stderr +++ b/tests/ui/typeck/conversion-methods.stderr @@ -2,28 +2,40 @@ error[E0308]: mismatched types --> $DIR/conversion-methods.rs:5:41 | LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—"; - | ------ ^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` - | | | - | | expected `String`, found `&str` + | ------ ^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `&str` + | | | expected due to this + | +help: try using a conversion method + | +LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—".to_string(); + | ++++++++++++ error[E0308]: mismatched types --> $DIR/conversion-methods.rs:6:40 | LL | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise"); - | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_path_buf()` - | | | - | | expected `PathBuf`, found `&Path` + | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `PathBuf`, found `&Path` + | | | expected due to this + | +help: try using a conversion method + | +LL | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise").to_path_buf(); + | ++++++++++++++ error[E0308]: mismatched types --> $DIR/conversion-methods.rs:9:40 | LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here - | ------ ^- help: try using a conversion method: `.to_string()` - | | | - | | expected `String`, found integer + | ------ ^ expected `String`, found integer + | | | expected due to this + | +help: try using a conversion method + | +LL | let _but_should_the_play: String = 2.to_string(); // Perhaps surprisingly, we suggest .to_string() here + | ++++++++++++ error[E0308]: mismatched types --> $DIR/conversion-methods.rs:12:47 From d6924441cd2b49678fcaf7cdee4e4a0263b7bdbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Jul 2025 17:34:39 +0000 Subject: [PATCH 35/36] Update test --- ...nt-suggest-borrowing-existing-borrow.fixed | 14 ++++- .../dont-suggest-borrowing-existing-borrow.rs | 12 +++- ...t-suggest-borrowing-existing-borrow.stderr | 58 +++++++++++++++---- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed index 95fd920dec229..00b92b42bb5cd 100644 --- a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed +++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed @@ -4,14 +4,24 @@ struct S; trait Trait { fn foo() {} } -impl Trait for &S {} impl Trait for &mut S {} +trait Trait2 { + fn bar() {} +} +impl Trait2 for &S {} +impl Trait2 for &mut S {} fn main() { let _ = <&str>::from("value"); //~^ ERROR the trait bound `str: From<_>` is not satisfied //~| ERROR the size for values of type `str` cannot be known at compilation time let _ = <&mut S>::foo(); //~^ ERROR the trait bound `S: Trait` is not satisfied - let _ = <&S>::foo(); + let _ = <&mut S>::foo(); + //~^ ERROR the trait bound `S: Trait` is not satisfied + let _ = <&mut S>::foo(); //~^ ERROR the trait bound `S: Trait` is not satisfied + let _ = <&mut S>::bar(); + //~^ ERROR the trait bound `S: Trait2` is not satisfied + let _ = <&S>::bar(); + //~^ ERROR the trait bound `S: Trait2` is not satisfied } diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs index f79d2465062ac..3059ccdffb458 100644 --- a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs +++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs @@ -4,8 +4,12 @@ struct S; trait Trait { fn foo() {} } -impl Trait for &S {} impl Trait for &mut S {} +trait Trait2 { + fn bar() {} +} +impl Trait2 for &S {} +impl Trait2 for &mut S {} fn main() { let _ = &str::from("value"); //~^ ERROR the trait bound `str: From<_>` is not satisfied @@ -14,4 +18,10 @@ fn main() { //~^ ERROR the trait bound `S: Trait` is not satisfied let _ = &S::foo(); //~^ ERROR the trait bound `S: Trait` is not satisfied + let _ = S::foo(); + //~^ ERROR the trait bound `S: Trait` is not satisfied + let _ = &mut S::bar(); + //~^ ERROR the trait bound `S: Trait2` is not satisfied + let _ = &S::bar(); + //~^ ERROR the trait bound `S: Trait2` is not satisfied } diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr index ac96ec76da7b1..c2e2fe941a6b0 100644 --- a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr +++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `str: From<_>` is not satisfied - --> $DIR/dont-suggest-borrowing-existing-borrow.rs:10:14 + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:14:14 | LL | let _ = &str::from("value"); | ^^^ the trait `From<_>` is not implemented for `str` @@ -17,35 +17,71 @@ LL | let _ = <&str>::from("value"); | + + error[E0277]: the trait bound `S: Trait` is not satisfied - --> $DIR/dont-suggest-borrowing-existing-borrow.rs:13:18 + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:17:18 | LL | let _ = &mut S::foo(); | ^ the trait `Trait` is not implemented for `S` | - = help: the following other types implement trait `Trait`: - &S - &mut S + = help: the trait `Trait` is implemented for `&mut S` help: you likely meant to call the associated function `foo` for type `&mut S`, but the code as written calls associated function `foo` on type `S` | LL | let _ = <&mut S>::foo(); | + + error[E0277]: the trait bound `S: Trait` is not satisfied - --> $DIR/dont-suggest-borrowing-existing-borrow.rs:15:14 + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:19:14 | LL | let _ = &S::foo(); | ^ the trait `Trait` is not implemented for `S` | - = help: the following other types implement trait `Trait`: + = help: the trait `Trait` is implemented for `&mut S` +help: you likely meant to call the associated function `foo` for type `&S`, but the code as written calls associated function `foo` on type `S` + | +LL - let _ = &S::foo(); +LL + let _ = <&mut S>::foo(); + | + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:21:13 + | +LL | let _ = S::foo(); + | ^ the trait `Trait` is not implemented for `S` + | +help: consider mutably borrowing here + | +LL | let _ = <&mut S>::foo(); + | +++++ + + +error[E0277]: the trait bound `S: Trait2` is not satisfied + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:23:18 + | +LL | let _ = &mut S::bar(); + | ^ the trait `Trait2` is not implemented for `S` + | + = help: the following other types implement trait `Trait2`: &S &mut S -help: you likely meant to call the associated function `foo` for type `&S`, but the code as written calls associated function `foo` on type `S` +help: you likely meant to call the associated function `bar` for type `&mut S`, but the code as written calls associated function `bar` on type `S` + | +LL | let _ = <&mut S>::bar(); + | + + + +error[E0277]: the trait bound `S: Trait2` is not satisfied + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:25:14 + | +LL | let _ = &S::bar(); + | ^ the trait `Trait2` is not implemented for `S` + | + = help: the following other types implement trait `Trait2`: + &S + &mut S +help: you likely meant to call the associated function `bar` for type `&S`, but the code as written calls associated function `bar` on type `S` | -LL | let _ = <&S>::foo(); +LL | let _ = <&S>::bar(); | + + error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/dont-suggest-borrowing-existing-borrow.rs:10:14 + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:14:14 | LL | let _ = &str::from("value"); | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -53,6 +89,6 @@ LL | let _ = &str::from("value"); = help: the trait `Sized` is not implemented for `str` = note: the return type of a function must have a statically known size -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. From 341f12df67946faf630e6a656f12e504e9721d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 10 Jul 2025 19:49:32 +0200 Subject: [PATCH 36/36] Properly track the depth when expanding free alias types --- compiler/rustc_middle/src/ty/util.rs | 6 ++++-- tests/ui/lazy-type-alias/deep-expansion.rs | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lazy-type-alias/deep-expansion.rs diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 69b8be3d9cbc3..fd80d85f198f5 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1052,9 +1052,11 @@ impl<'tcx> TypeFolder> for FreeAliasTypeExpander<'tcx> { } self.depth += 1; - ensure_sufficient_stack(|| { + let ty = ensure_sufficient_stack(|| { self.tcx.type_of(alias.def_id).instantiate(self.tcx, alias.args).fold_with(self) - }) + }); + self.depth -= 1; + ty } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { diff --git a/tests/ui/lazy-type-alias/deep-expansion.rs b/tests/ui/lazy-type-alias/deep-expansion.rs new file mode 100644 index 0000000000000..c4461abdb8143 --- /dev/null +++ b/tests/ui/lazy-type-alias/deep-expansion.rs @@ -0,0 +1,20 @@ +// In several type analysis passes we employ a specialized expansion procedure. +// This procedure used to incorrectly track expansion depth (growing much faster +// than normalization depth) resulting in its internal assertion triggering. +// +// issue: +//@ check-pass +#![feature(lazy_type_alias)] +#![expect(incomplete_features)] + +type T0 = (T1, T1, T1, T1); +type T1 = (T2, T2, T2, T2); +type T2 = (T3, T3, T3, T3); +type T3 = (T4, T4, T4, T4); +type T4 = (T5, T5, T5, T5); +type T5 = (T6, T6, T6, T6); +type T6 = (T7, T7, T7, T7); +type T7 = (); + +fn accept(_: T0) {} +fn main() {}