From 955a32232eeb96398487ccfc32957453967a8003 Mon Sep 17 00:00:00 2001 From: Ohad Ravid Date: Fri, 21 Aug 2026 03:38:30 -0700 Subject: [PATCH 01/13] Avoid arming the Windows TLS destructor guard in fibers (cherry picked from commit 373266b87ea72e4f2ca7e00b5f8b4565f3153e6d) --- .../std/src/sys/thread_local/guard/windows.rs | 6 ++ library/std/src/thread/local.rs | 9 ++- library/std/tests/thread_local/tests.rs | 56 +++++++++++++++++-- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/library/std/src/sys/thread_local/guard/windows.rs b/library/std/src/sys/thread_local/guard/windows.rs index d59631d5d6ca3..212e8ccdc9d60 100644 --- a/library/std/src/sys/thread_local/guard/windows.rs +++ b/library/std/src/sys/thread_local/guard/windows.rs @@ -176,6 +176,12 @@ pub fn enable() { } }; + // We must not set the key if we are in a fiber, since deleting that fiber from a thread + // will cause the destructors to run before thread exit. + if is_thread_a_fiber() { + return; + } + // Setting the key's value to non-zero will cause the dtor callback to be called when the thread exits. unsafe { set(key, ptr::without_provenance(1)) }; } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 7a05a962e2ac0..18b0f3263ad59 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -98,17 +98,16 @@ use crate::fmt; /// run on the thread that causes the process to exit. This is because the /// other threads may be forcibly terminated. /// -/// If a thread is [converted into a fiber], destructors will not be run unless -/// the fiber is [converted back into a thread] before the underlying thread exits. +/// TLS destructors may be leaked if a thread exits while [converted into a fiber], +/// or if Rust TLS destructor support is first needed while running in a fiber. /// /// If a process loads a Rust `cdylib`, it must not cause the Rust TLS destructor support -// to be initialized for the first time during process shutdown. +/// to be initialized for the first time during process shutdown. /// /// When dynamically unloading a Rust `cdylib`, pending TLS destructors may run -// during the unload or may be leaked. +/// during the unload or may be leaked. /// /// [converted into a fiber]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-convertthreadtofiber -/// [converted back into a thread]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-convertfibertothread /// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices /// [`with`]: LocalKey::with #[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")] diff --git a/library/std/tests/thread_local/tests.rs b/library/std/tests/thread_local/tests.rs index 1a25d91e43bc0..df9b99ef0af64 100644 --- a/library/std/tests/thread_local/tests.rs +++ b/library/std/tests/thread_local/tests.rs @@ -416,9 +416,17 @@ fn fiber_does_not_trigger_dtor() { unsafe extern "system" { fn ConvertFiberToThread() -> i32; fn ConvertThreadToFiber(lpParameter: *const c_void) -> *mut c_void; + fn CreateFiber( + dwStackSize: usize, + lpStartAddress: unsafe extern "system" fn(*mut c_void), + lpParameter: *mut c_void, + ) -> *mut c_void; + fn DeleteFiber(lpFiber: *mut c_void); + fn SwitchToFiber(lpFiber: *mut c_void); } thread_local!(static FOO: UnsafeCell> = UnsafeCell::new(None)); + let signal = Signal::default(); let signal2 = signal.clone(); @@ -438,13 +446,49 @@ fn fiber_does_not_trigger_dtor() { // As long as we stop using fibers before thread teardown, everything works as expected. let signal2 = signal.clone(); let t = thread::spawn(move || unsafe { - let mut signal = Some(signal2); - let _ = ConvertThreadToFiber(ptr::null()); - FOO.with(|f| { - *f.get() = Some(NotifyOnDrop(signal.take().unwrap())); - }); - let _ = ConvertFiberToThread(); + struct FiberData { + main: *mut c_void, + signal: Signal, + } + + unsafe extern "system" fn fiber_start(data: *mut c_void) { + let data = unsafe { &mut *data.cast::() }; + + // Set the value while this fiber is current. + // This must NOT arm the FLS cleanup guard for the fiber. + FOO.with(|f| unsafe { + *f.get() = Some(NotifyOnDrop(data.signal.clone())); + }); + + unsafe { + SwitchToFiber(data.main); + } + } + + let main = ConvertThreadToFiber(ptr::null()); + assert!(!main.is_null()); + + let mut data = FiberData { main, signal: signal2.clone() }; + let foo = CreateFiber(0, fiber_start, ptr::from_mut(&mut data).cast()); + assert!(!foo.is_null()); + + // Run `foo`, which sets FOO while `foo` is the current fiber, + // then switches back to main. + SwitchToFiber(foo); + + // Convert main back to a thread before deleting `foo`. + assert_ne!(ConvertFiberToThread(), 0); + + // Deleting `foo` must not trigger dtors like a thread teardown. + DeleteFiber(foo); + assert!(!signal2.is_set()); + + // Arm the guard now from the normal thread. + // `FOO`'s destructor is already registered, so it will run when the thread exits. + thread_local!(static BAR: UnsafeCell> = UnsafeCell::new(None)); + BAR.with(|_| {}); }); + signal.wait(); assert!(signal.is_set()); t.join().unwrap(); From 8672be1f1daed5b06759ca1c00175e8de8cddefc Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 19 Aug 2026 16:07:08 +0200 Subject: [PATCH 02/13] Revert "x86: Followup to add const for pack intrinsics and tests" (cherry picked from commit 50c4cbbb9c190a43f50a12089fd88b25a39f1f8b) --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 36 ++-- .../crates/core_arch/src/x86/avx512bw.rs | 191 ++++++------------ .../stdarch/crates/core_arch/src/x86/sse2.rs | 27 ++- .../stdarch/crates/core_arch/src/x86/sse41.rs | 9 +- 4 files changed, 94 insertions(+), 169 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 6925ba8e27028..68b8d57cfdf19 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -2323,11 +2323,10 @@ pub const fn _mm256_or_si256(a: __m256i, b: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpacksswb))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i { unsafe { - let max = simd_splat(i8::MAX as i16); - let min = simd_splat(i8::MIN as i16); + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i16x16(), max), min) .as_m256i() @@ -2357,11 +2356,10 @@ pub const fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpackssdw))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i { unsafe { - let max = simd_splat(i16::MAX as i32); - let min = simd_splat(i16::MIN as i32); + let max = simd_splat(i32::from(i16::MAX)); + let min = simd_splat(i32::from(i16::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i32x8(), max), min) .as_m256i() @@ -2391,11 +2389,10 @@ pub const fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpackuswb))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i { unsafe { - let max = simd_splat(u8::MAX as i16); - let min = simd_splat(u8::MIN as i16); + let max = simd_splat(i16::from(u8::MAX)); + let min = simd_splat(i16::from(u8::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i16x16(), max), min) .as_m256i() @@ -2425,11 +2422,10 @@ pub const fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpackusdw))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_packus_epi32(a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_packus_epi32(a: __m256i, b: __m256i) -> __m256i { unsafe { - let max = simd_splat(u16::MAX as i32); - let min = simd_splat(u16::MIN as i32); + let max = simd_splat(i32::from(u16::MAX)); + let min = simd_splat(i32::from(u16::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i32x8(), max), min) .as_m256i() @@ -5068,7 +5064,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_packs_epi16() { + fn test_mm256_packs_epi16() { let a = _mm256_set1_epi16(2); let b = _mm256_set1_epi16(4); let r = _mm256_packs_epi16(a, b); @@ -5084,7 +5080,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_packs_epi32() { + fn test_mm256_packs_epi32() { let a = _mm256_set1_epi32(2); let b = _mm256_set1_epi32(4); let r = _mm256_packs_epi32(a, b); @@ -5094,7 +5090,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_packus_epi16() { + fn test_mm256_packus_epi16() { let a = _mm256_set1_epi16(2); let b = _mm256_set1_epi16(4); let r = _mm256_packus_epi16(a, b); @@ -5110,7 +5106,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_packus_epi32() { + fn test_mm256_packus_epi32() { let a = _mm256_set1_epi32(2); let b = _mm256_set1_epi32(4); let r = _mm256_packus_epi32(a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 50d57b4964489..c1eb29c7ca81f 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -6523,11 +6523,10 @@ pub fn _mm_maskz_maddubs_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i { unsafe { - let max = simd_splat(i16::MAX as i32); - let min = simd_splat(i16::MIN as i32); + let max = simd_splat(i32::from(i16::MAX)); + let min = simd_splat(i32::from(i16::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i32x16(), max), min) .as_m512i() @@ -6560,13 +6559,7 @@ pub const fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_packs_epi32( - src: __m512i, - k: __mmask32, - a: __m512i, - b: __m512i, -) -> __m512i { +pub fn _mm512_mask_packs_epi32(src: __m512i, k: __mmask32, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packs_epi32(a, b).as_i16x32(); transmute(simd_select_bitmask(k, pack, src.as_i16x32())) @@ -6580,8 +6573,7 @@ pub const fn _mm512_mask_packs_epi32( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_packs_epi32(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_maskz_packs_epi32(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packs_epi32(a, b).as_i16x32(); transmute(simd_select_bitmask(k, pack, i16x32::ZERO)) @@ -6595,13 +6587,7 @@ pub const fn _mm512_maskz_packs_epi32(k: __mmask32, a: __m512i, b: __m512i) -> _ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_packs_epi32( - src: __m256i, - k: __mmask16, - a: __m256i, - b: __m256i, -) -> __m256i { +pub fn _mm256_mask_packs_epi32(src: __m256i, k: __mmask16, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packs_epi32(a, b).as_i16x16(); transmute(simd_select_bitmask(k, pack, src.as_i16x16())) @@ -6629,8 +6615,7 @@ pub fn _mm256_maskz_packs_epi32(k: __mmask16, a: __m256i, b: __m256i) -> __m256i #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_packs_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_mask_packs_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packs_epi32(a, b).as_i16x8(); transmute(simd_select_bitmask(k, pack, src.as_i16x8())) @@ -6644,8 +6629,7 @@ pub const fn _mm_mask_packs_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m1 #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_packs_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_maskz_packs_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packs_epi32(a, b).as_i16x8(); transmute(simd_select_bitmask(k, pack, i16x8::ZERO)) @@ -6659,11 +6643,10 @@ pub const fn _mm_maskz_packs_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m12 #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_packs_epi16(a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_packs_epi16(a: __m512i, b: __m512i) -> __m512i { unsafe { - let max = simd_splat(i8::MAX as i16); - let min = simd_splat(i8::MIN as i16); + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i16x32(), max), min) .as_m512i() @@ -6696,13 +6679,7 @@ pub const fn _mm512_packs_epi16(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_packs_epi16( - src: __m512i, - k: __mmask64, - a: __m512i, - b: __m512i, -) -> __m512i { +pub fn _mm512_mask_packs_epi16(src: __m512i, k: __mmask64, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packs_epi16(a, b).as_i8x64(); transmute(simd_select_bitmask(k, pack, src.as_i8x64())) @@ -6716,8 +6693,7 @@ pub const fn _mm512_mask_packs_epi16( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_packs_epi16(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_maskz_packs_epi16(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packs_epi16(a, b).as_i8x64(); transmute(simd_select_bitmask(k, pack, i8x64::ZERO)) @@ -6731,13 +6707,7 @@ pub const fn _mm512_maskz_packs_epi16(k: __mmask64, a: __m512i, b: __m512i) -> _ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_packs_epi16( - src: __m256i, - k: __mmask32, - a: __m256i, - b: __m256i, -) -> __m256i { +pub fn _mm256_mask_packs_epi16(src: __m256i, k: __mmask32, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packs_epi16(a, b).as_i8x32(); transmute(simd_select_bitmask(k, pack, src.as_i8x32())) @@ -6751,8 +6721,7 @@ pub const fn _mm256_mask_packs_epi16( #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_packs_epi16(k: __mmask32, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_maskz_packs_epi16(k: __mmask32, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packs_epi16(a, b).as_i8x32(); transmute(simd_select_bitmask(k, pack, i8x32::ZERO)) @@ -6766,8 +6735,7 @@ pub const fn _mm256_maskz_packs_epi16(k: __mmask32, a: __m256i, b: __m256i) -> _ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_packs_epi16(src: __m128i, k: __mmask16, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_mask_packs_epi16(src: __m128i, k: __mmask16, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packs_epi16(a, b).as_i8x16(); transmute(simd_select_bitmask(k, pack, src.as_i8x16())) @@ -6781,8 +6749,7 @@ pub const fn _mm_mask_packs_epi16(src: __m128i, k: __mmask16, a: __m128i, b: __m #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_packs_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_maskz_packs_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packs_epi16(a, b).as_i8x16(); transmute(simd_select_bitmask(k, pack, i8x16::ZERO)) @@ -6796,11 +6763,10 @@ pub const fn _mm_maskz_packs_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m1 #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_packus_epi32(a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_packus_epi32(a: __m512i, b: __m512i) -> __m512i { unsafe { - let max = simd_splat(u16::MAX as i32); - let min = simd_splat(u16::MIN as i32); + let max = simd_splat(i32::from(u16::MAX)); + let min = simd_splat(i32::from(u16::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i32x16(), max), min) .as_m512i() @@ -6833,13 +6799,7 @@ pub const fn _mm512_packus_epi32(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_packus_epi32( - src: __m512i, - k: __mmask32, - a: __m512i, - b: __m512i, -) -> __m512i { +pub fn _mm512_mask_packus_epi32(src: __m512i, k: __mmask32, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packus_epi32(a, b).as_i16x32(); transmute(simd_select_bitmask(k, pack, src.as_i16x32())) @@ -6853,8 +6813,7 @@ pub const fn _mm512_mask_packus_epi32( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_packus_epi32(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_maskz_packus_epi32(k: __mmask32, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packus_epi32(a, b).as_i16x32(); transmute(simd_select_bitmask(k, pack, i16x32::ZERO)) @@ -6868,13 +6827,7 @@ pub const fn _mm512_maskz_packus_epi32(k: __mmask32, a: __m512i, b: __m512i) -> #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_packus_epi32( - src: __m256i, - k: __mmask16, - a: __m256i, - b: __m256i, -) -> __m256i { +pub fn _mm256_mask_packus_epi32(src: __m256i, k: __mmask16, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packus_epi32(a, b).as_i16x16(); transmute(simd_select_bitmask(k, pack, src.as_i16x16())) @@ -6888,8 +6841,7 @@ pub const fn _mm256_mask_packus_epi32( #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_packus_epi32(k: __mmask16, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_maskz_packus_epi32(k: __mmask16, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packus_epi32(a, b).as_i16x16(); transmute(simd_select_bitmask(k, pack, i16x16::ZERO)) @@ -6903,8 +6855,7 @@ pub const fn _mm256_maskz_packus_epi32(k: __mmask16, a: __m256i, b: __m256i) -> #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_packus_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_mask_packus_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packus_epi32(a, b).as_i16x8(); transmute(simd_select_bitmask(k, pack, src.as_i16x8())) @@ -6918,8 +6869,7 @@ pub const fn _mm_mask_packus_epi32(src: __m128i, k: __mmask8, a: __m128i, b: __m #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_packus_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_maskz_packus_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packus_epi32(a, b).as_i16x8(); transmute(simd_select_bitmask(k, pack, i16x8::ZERO)) @@ -6933,11 +6883,10 @@ pub const fn _mm_maskz_packus_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m1 #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_packus_epi16(a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_packus_epi16(a: __m512i, b: __m512i) -> __m512i { unsafe { - let max = simd_splat(u8::MAX as i16); - let min = simd_splat(u8::MIN as i16); + let max = simd_splat(i16::from(u8::MAX)); + let min = simd_splat(i16::from(u8::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i16x32(), max), min) .as_m512i() @@ -6970,13 +6919,7 @@ pub const fn _mm512_packus_epi16(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_packus_epi16( - src: __m512i, - k: __mmask64, - a: __m512i, - b: __m512i, -) -> __m512i { +pub fn _mm512_mask_packus_epi16(src: __m512i, k: __mmask64, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packus_epi16(a, b).as_i8x64(); transmute(simd_select_bitmask(k, pack, src.as_i8x64())) @@ -6990,8 +6933,7 @@ pub const fn _mm512_mask_packus_epi16( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_packus_epi16(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_maskz_packus_epi16(k: __mmask64, a: __m512i, b: __m512i) -> __m512i { unsafe { let pack = _mm512_packus_epi16(a, b).as_i8x64(); transmute(simd_select_bitmask(k, pack, i8x64::ZERO)) @@ -7005,13 +6947,7 @@ pub const fn _mm512_maskz_packus_epi16(k: __mmask64, a: __m512i, b: __m512i) -> #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_packus_epi16( - src: __m256i, - k: __mmask32, - a: __m256i, - b: __m256i, -) -> __m256i { +pub fn _mm256_mask_packus_epi16(src: __m256i, k: __mmask32, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packus_epi16(a, b).as_i8x32(); transmute(simd_select_bitmask(k, pack, src.as_i8x32())) @@ -7025,8 +6961,7 @@ pub const fn _mm256_mask_packus_epi16( #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_packus_epi16(k: __mmask32, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_maskz_packus_epi16(k: __mmask32, a: __m256i, b: __m256i) -> __m256i { unsafe { let pack = _mm256_packus_epi16(a, b).as_i8x32(); transmute(simd_select_bitmask(k, pack, i8x32::ZERO)) @@ -7040,8 +6975,7 @@ pub const fn _mm256_maskz_packus_epi16(k: __mmask32, a: __m256i, b: __m256i) -> #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_packus_epi16(src: __m128i, k: __mmask16, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_mask_packus_epi16(src: __m128i, k: __mmask16, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packus_epi16(a, b).as_i8x16(); transmute(simd_select_bitmask(k, pack, src.as_i8x16())) @@ -7055,8 +6989,7 @@ pub const fn _mm_mask_packus_epi16(src: __m128i, k: __mmask16, a: __m128i, b: __ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_packus_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_maskz_packus_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { unsafe { let pack = _mm_packus_epi16(a, b).as_i8x16(); transmute(simd_select_bitmask(k, pack, i8x16::ZERO)) @@ -17860,7 +17793,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_packs_epi32() { + fn test_mm512_packs_epi32() { let a = _mm512_set1_epi32(i32::MAX); let b = _mm512_set1_epi32(1); let r = _mm512_packs_epi32(a, b); @@ -17871,7 +17804,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_packs_epi32() { + fn test_mm512_mask_packs_epi32() { let a = _mm512_set1_epi32(i32::MAX); let b = _mm512_set1_epi32(1 << 16 | 1); let r = _mm512_mask_packs_epi32(a, 0, a, b); @@ -17884,7 +17817,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_packs_epi32() { + fn test_mm512_maskz_packs_epi32() { let a = _mm512_set1_epi32(i32::MAX); let b = _mm512_set1_epi32(1); let r = _mm512_maskz_packs_epi32(0, a, b); @@ -17897,7 +17830,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_packs_epi32() { + fn test_mm256_mask_packs_epi32() { let a = _mm256_set1_epi32(i32::MAX); let b = _mm256_set1_epi32(1 << 16 | 1); let r = _mm256_mask_packs_epi32(a, 0, a, b); @@ -17921,7 +17854,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_packs_epi32() { + fn test_mm_mask_packs_epi32() { let a = _mm_set1_epi32(i32::MAX); let b = _mm_set1_epi32(1 << 16 | 1); let r = _mm_mask_packs_epi32(a, 0, a, b); @@ -17932,7 +17865,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_packs_epi32() { + fn test_mm_maskz_packs_epi32() { let a = _mm_set1_epi32(i32::MAX); let b = _mm_set1_epi32(1); let r = _mm_maskz_packs_epi32(0, a, b); @@ -17943,7 +17876,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_packs_epi16() { + fn test_mm512_packs_epi16() { let a = _mm512_set1_epi16(i16::MAX); let b = _mm512_set1_epi16(1); let r = _mm512_packs_epi16(a, b); @@ -17956,7 +17889,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_packs_epi16() { + fn test_mm512_mask_packs_epi16() { let a = _mm512_set1_epi16(i16::MAX); let b = _mm512_set1_epi16(1 << 8 | 1); let r = _mm512_mask_packs_epi16(a, 0, a, b); @@ -17976,7 +17909,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_packs_epi16() { + fn test_mm512_maskz_packs_epi16() { let a = _mm512_set1_epi16(i16::MAX); let b = _mm512_set1_epi16(1); let r = _mm512_maskz_packs_epi16(0, a, b); @@ -17995,7 +17928,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_packs_epi16() { + fn test_mm256_mask_packs_epi16() { let a = _mm256_set1_epi16(i16::MAX); let b = _mm256_set1_epi16(1 << 8 | 1); let r = _mm256_mask_packs_epi16(a, 0, a, b); @@ -18008,7 +17941,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_packs_epi16() { + fn test_mm256_maskz_packs_epi16() { let a = _mm256_set1_epi16(i16::MAX); let b = _mm256_set1_epi16(1); let r = _mm256_maskz_packs_epi16(0, a, b); @@ -18021,7 +17954,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_packs_epi16() { + fn test_mm_mask_packs_epi16() { let a = _mm_set1_epi16(i16::MAX); let b = _mm_set1_epi16(1 << 8 | 1); let r = _mm_mask_packs_epi16(a, 0, a, b); @@ -18033,7 +17966,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_packs_epi16() { + fn test_mm_maskz_packs_epi16() { let a = _mm_set1_epi16(i16::MAX); let b = _mm_set1_epi16(1); let r = _mm_maskz_packs_epi16(0, a, b); @@ -18045,7 +17978,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_packus_epi32() { + fn test_mm512_packus_epi32() { let a = _mm512_set1_epi32(-1); let b = _mm512_set1_epi32(1); let r = _mm512_packus_epi32(a, b); @@ -18056,7 +17989,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_packus_epi32() { + fn test_mm512_mask_packus_epi32() { let a = _mm512_set1_epi32(-1); let b = _mm512_set1_epi32(1 << 16 | 1); let r = _mm512_mask_packus_epi32(a, 0, a, b); @@ -18069,7 +18002,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_packus_epi32() { + fn test_mm512_maskz_packus_epi32() { let a = _mm512_set1_epi32(-1); let b = _mm512_set1_epi32(1); let r = _mm512_maskz_packus_epi32(0, a, b); @@ -18082,7 +18015,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_packus_epi32() { + fn test_mm256_mask_packus_epi32() { let a = _mm256_set1_epi32(-1); let b = _mm256_set1_epi32(1 << 16 | 1); let r = _mm256_mask_packus_epi32(a, 0, a, b); @@ -18093,7 +18026,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_packus_epi32() { + fn test_mm256_maskz_packus_epi32() { let a = _mm256_set1_epi32(-1); let b = _mm256_set1_epi32(1); let r = _mm256_maskz_packus_epi32(0, a, b); @@ -18104,7 +18037,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_packus_epi32() { + fn test_mm_mask_packus_epi32() { let a = _mm_set1_epi32(-1); let b = _mm_set1_epi32(1 << 16 | 1); let r = _mm_mask_packus_epi32(a, 0, a, b); @@ -18115,7 +18048,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_packus_epi32() { + fn test_mm_maskz_packus_epi32() { let a = _mm_set1_epi32(-1); let b = _mm_set1_epi32(1); let r = _mm_maskz_packus_epi32(0, a, b); @@ -18126,7 +18059,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_packus_epi16() { + fn test_mm512_packus_epi16() { let a = _mm512_set1_epi16(-1); let b = _mm512_set1_epi16(1); let r = _mm512_packus_epi16(a, b); @@ -18139,7 +18072,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_packus_epi16() { + fn test_mm512_mask_packus_epi16() { let a = _mm512_set1_epi16(-1); let b = _mm512_set1_epi16(1 << 8 | 1); let r = _mm512_mask_packus_epi16(a, 0, a, b); @@ -18159,7 +18092,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_packus_epi16() { + fn test_mm512_maskz_packus_epi16() { let a = _mm512_set1_epi16(-1); let b = _mm512_set1_epi16(1); let r = _mm512_maskz_packus_epi16(0, a, b); @@ -18178,7 +18111,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_packus_epi16() { + fn test_mm256_mask_packus_epi16() { let a = _mm256_set1_epi16(-1); let b = _mm256_set1_epi16(1 << 8 | 1); let r = _mm256_mask_packus_epi16(a, 0, a, b); @@ -18191,7 +18124,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_packus_epi16() { + fn test_mm256_maskz_packus_epi16() { let a = _mm256_set1_epi16(-1); let b = _mm256_set1_epi16(1); let r = _mm256_maskz_packus_epi16(0, a, b); @@ -18204,7 +18137,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_packus_epi16() { + fn test_mm_mask_packus_epi16() { let a = _mm_set1_epi16(-1); let b = _mm_set1_epi16(1 << 8 | 1); let r = _mm_mask_packus_epi16(a, 0, a, b); @@ -18215,7 +18148,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_packus_epi16() { + fn test_mm_maskz_packus_epi16() { let a = _mm_set1_epi16(-1); let b = _mm_set1_epi16(1); let r = _mm_maskz_packus_epi16(0, a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index 66ebec22e11de..b719882c4864c 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -1498,11 +1498,10 @@ pub const fn _mm_move_epi64(a: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(packsswb))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i { unsafe { - let max = simd_splat(i8::MAX as i16); - let min = simd_splat(i8::MIN as i16); + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i16x8(), max), min) .as_m128i() @@ -1528,11 +1527,10 @@ pub const fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(packssdw))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i { unsafe { - let max = simd_splat(i16::MAX as i32); - let min = simd_splat(i16::MIN as i32); + let max = simd_splat(i32::from(i16::MAX)); + let min = simd_splat(i32::from(i16::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i32x4(), max), min); let clamped_b = simd_imax(simd_imin(b.as_i32x4(), max), min); @@ -1554,11 +1552,10 @@ pub const fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(packuswb))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_packus_epi16(a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_packus_epi16(a: __m128i, b: __m128i) -> __m128i { unsafe { - let max = simd_splat(u8::MAX as i16); - let min = simd_splat(u8::MIN as i16); + let max = simd_splat(i16::from(u8::MAX)); + let min = simd_splat(i16::from(u8::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i16x8(), max), min) .as_m128i() @@ -4338,7 +4335,7 @@ mod tests { } #[simd_test(enable = "sse2")] - const fn test_mm_packs_epi16() { + fn test_mm_packs_epi16() { let a = _mm_setr_epi16(0x80, -0x81, 0, 0, 0, 0, 0, 0); let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -0x81, 0x80); let r = _mm_packs_epi16(a, b); @@ -4352,7 +4349,7 @@ mod tests { } #[simd_test(enable = "sse2")] - const fn test_mm_packs_epi32() { + fn test_mm_packs_epi32() { let a = _mm_setr_epi32(0x8000, -0x8001, 0, 0); let b = _mm_setr_epi32(0, 0, -0x8001, 0x8000); let r = _mm_packs_epi32(a, b); @@ -4363,7 +4360,7 @@ mod tests { } #[simd_test(enable = "sse2")] - const fn test_mm_packus_epi16() { + fn test_mm_packus_epi16() { let a = _mm_setr_epi16(0x100, -1, 0, 0, 0, 0, 0, 0); let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -1, 0x100); let r = _mm_packus_epi16(a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/sse41.rs b/library/stdarch/crates/core_arch/src/x86/sse41.rs index d981166ff08c9..38e7ab39c4dac 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse41.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse41.rs @@ -426,11 +426,10 @@ pub const fn _mm_min_epu32(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse4.1")] #[cfg_attr(test, assert_instr(packusdw))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_packus_epi32(a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_packus_epi32(a: __m128i, b: __m128i) -> __m128i { unsafe { - let max = simd_splat(u16::MAX as i32); - let min = simd_splat(u16::MIN as i32); + let max = simd_splat(i32::from(u16::MAX)); + let min = simd_splat(i32::from(u16::MIN)); let clamped_a = simd_imax(simd_imin(a.as_i32x4(), max), min) .as_m128i() @@ -1471,7 +1470,7 @@ mod tests { } #[simd_test(enable = "sse4.1")] - const fn test_mm_packus_epi32() { + fn test_mm_packus_epi32() { let a = _mm_setr_epi32(1, 2, 3, 4); let b = _mm_setr_epi32(-1, -2, -3, -4); let r = _mm_packus_epi32(a, b); From 5ca95c07e0be58aeef1fb1ea5541709ef29c67bf Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 19 Aug 2026 19:38:56 +0200 Subject: [PATCH 03/13] Revert "x86: use `simd::intrinsics` for saturating packs" (cherry picked from commit 7b002b705463d235a53c31f1801e5ee8050a552d) --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 108 +++------------- .../crates/core_arch/src/x86/avx512bw.rs | 117 ++---------------- .../stdarch/crates/core_arch/src/x86/sse2.rs | 67 ++-------- .../stdarch/crates/core_arch/src/x86/sse41.rs | 23 +--- 4 files changed, 45 insertions(+), 270 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 68b8d57cfdf19..e2c3865810fa8 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -2315,7 +2315,7 @@ pub const fn _mm256_or_si256(a: __m256i, b: __m256i) -> __m256i { unsafe { transmute(simd_or(a.as_i32x8(), b.as_i32x8())) } } -/// Converts packed signed 16-bit integers from `a` and `b` to packed 8-bit integers +/// Converts packed 16-bit integers from `a` and `b` to packed 8-bit integers /// using signed saturation /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi16) @@ -2324,31 +2324,10 @@ pub const fn _mm256_or_si256(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vpacksswb))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { - let max = simd_splat(i16::from(i8::MAX)); - let min = simd_splat(i16::from(i8::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i16x16(), max), min) - .as_m256i() - .as_i8x32(); - let clamped_b = simd_imax(simd_imin(b.as_i16x16(), max), min) - .as_m256i() - .as_i8x32(); - - #[rustfmt::skip] - const IDXS: [u32; 32] = [ - 00, 02, 04, 06, 08, 10, 12, 14, // a-lo i16 to i8 conversions - 32, 34, 36, 38, 40, 42, 44, 46, // b-lo - 16, 18, 20, 22, 24, 26, 28, 30, // a-hi - 48, 50, 52, 54, 56, 58, 60, 62, // b-hi - ]; - let result: i8x32 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m256i() - } + unsafe { transmute(packsswb(a.as_i16x16(), b.as_i16x16())) } } -/// Converts packed signed 32-bit integers from `a` and `b` to packed 16-bit integers +/// Converts packed 32-bit integers from `a` and `b` to packed 16-bit integers /// using signed saturation /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32) @@ -2357,31 +2336,10 @@ pub fn _mm256_packs_epi16(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vpackssdw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i { - unsafe { - let max = simd_splat(i32::from(i16::MAX)); - let min = simd_splat(i32::from(i16::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i32x8(), max), min) - .as_m256i() - .as_i16x16(); - let clamped_b = simd_imax(simd_imin(b.as_i32x8(), max), min) - .as_m256i() - .as_i16x16(); - - #[rustfmt::skip] - const IDXS: [u32; 16] = [ - 00, 02, 04, 06, // a-lo i32 to i16 conversions - 16, 18, 20, 22, // b-lo - 08, 10, 12, 14, // a-hi - 24, 26, 28, 30, // b-hi - ]; - let result: i16x16 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m256i() - } + unsafe { transmute(packssdw(a.as_i32x8(), b.as_i32x8())) } } -/// Converts packed signed 16-bit integers from `a` and `b` to packed 8-bit integers +/// Converts packed 16-bit integers from `a` and `b` to packed 8-bit integers /// using unsigned saturation /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16) @@ -2390,31 +2348,10 @@ pub fn _mm256_packs_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vpackuswb))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { - let max = simd_splat(i16::from(u8::MAX)); - let min = simd_splat(i16::from(u8::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i16x16(), max), min) - .as_m256i() - .as_i8x32(); - let clamped_b = simd_imax(simd_imin(b.as_i16x16(), max), min) - .as_m256i() - .as_i8x32(); - - #[rustfmt::skip] - const IDXS: [u32; 32] = [ - 00, 02, 04, 06, 08, 10, 12, 14, // a-lo i16 to u8 conversions - 32, 34, 36, 38, 40, 42, 44, 46, // b-lo - 16, 18, 20, 22, 24, 26, 28, 30, // a-hi - 48, 50, 52, 54, 56, 58, 60, 62, // b-hi - ]; - let result: i8x32 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m256i() - } + unsafe { transmute(packuswb(a.as_i16x16(), b.as_i16x16())) } } -/// Converts packed signed 32-bit integers from `a` and `b` to packed 16-bit integers +/// Converts packed 32-bit integers from `a` and `b` to packed 16-bit integers /// using unsigned saturation /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi32) @@ -2423,28 +2360,7 @@ pub fn _mm256_packus_epi16(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vpackusdw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_packus_epi32(a: __m256i, b: __m256i) -> __m256i { - unsafe { - let max = simd_splat(i32::from(u16::MAX)); - let min = simd_splat(i32::from(u16::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i32x8(), max), min) - .as_m256i() - .as_i16x16(); - let clamped_b = simd_imax(simd_imin(b.as_i32x8(), max), min) - .as_m256i() - .as_i16x16(); - - #[rustfmt::skip] - const IDXS: [u32; 16] = [ - 00, 02, 04, 06, // a-lo i32 to u16 conversions - 16, 18, 20, 22, // b-lo - 08, 10, 12, 14, // a-hi - 24, 26, 28, 30, // b-hi - ]; - let result: i16x16 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m256i() - } + unsafe { transmute(packusdw(a.as_i32x8(), b.as_i32x8())) } } /// Permutes packed 32-bit integers from `a` according to the content of `b`. @@ -3911,6 +3827,14 @@ unsafe extern "unadjusted" { fn mpsadbw(a: u8x32, b: u8x32, imm8: i8) -> u16x16; #[link_name = "llvm.x86.avx2.pmul.hr.sw"] fn pmulhrsw(a: i16x16, b: i16x16) -> i16x16; + #[link_name = "llvm.x86.avx2.packsswb"] + fn packsswb(a: i16x16, b: i16x16) -> i8x32; + #[link_name = "llvm.x86.avx2.packssdw"] + fn packssdw(a: i32x8, b: i32x8) -> i16x16; + #[link_name = "llvm.x86.avx2.packuswb"] + fn packuswb(a: i16x16, b: i16x16) -> u8x32; + #[link_name = "llvm.x86.avx2.packusdw"] + fn packusdw(a: i32x8, b: i32x8) -> u16x16; #[link_name = "llvm.x86.avx2.psad.bw"] fn psadbw(a: u8x32, b: u8x32) -> u64x4; #[link_name = "llvm.x86.avx2.psign.b"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index c1eb29c7ca81f..0747b65b35eae 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -6524,32 +6524,7 @@ pub fn _mm_maskz_maddubs_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackssdw))] pub fn _mm512_packs_epi32(a: __m512i, b: __m512i) -> __m512i { - unsafe { - let max = simd_splat(i32::from(i16::MAX)); - let min = simd_splat(i32::from(i16::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i32x16(), max), min) - .as_m512i() - .as_i16x32(); - let clamped_b = simd_imax(simd_imin(b.as_i32x16(), max), min) - .as_m512i() - .as_i16x32(); - - #[rustfmt::skip] - const IDXS: [u32; 32] = [ - 00, 02, 04, 06, - 32, 34, 36, 38, - 08, 10, 12, 14, - 40, 42, 44, 46, - 16, 18, 20, 22, - 48, 50, 52, 54, - 24, 26, 28, 30, - 56, 58, 60, 62, - ]; - let result: i16x32 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m512i() - } + unsafe { transmute(vpackssdw(a.as_i32x16(), b.as_i32x16())) } } /// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6644,32 +6619,7 @@ pub fn _mm_maskz_packs_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpacksswb))] pub fn _mm512_packs_epi16(a: __m512i, b: __m512i) -> __m512i { - unsafe { - let max = simd_splat(i16::from(i8::MAX)); - let min = simd_splat(i16::from(i8::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i16x32(), max), min) - .as_m512i() - .as_i8x64(); - let clamped_b = simd_imax(simd_imin(b.as_i16x32(), max), min) - .as_m512i() - .as_i8x64(); - - #[rustfmt::skip] - const IDXS: [u32; 64] = [ - 000, 002, 004, 006, 008, 010, 012, 014, - 064, 066, 068, 070, 072, 074, 076, 078, - 016, 018, 020, 022, 024, 026, 028, 030, - 080, 082, 084, 086, 088, 090, 092, 094, - 032, 034, 036, 038, 040, 042, 044, 046, - 096, 098, 100, 102, 104, 106, 108, 110, - 048, 050, 052, 054, 056, 058, 060, 062, - 112, 114, 116, 118, 120, 122, 124, 126, - ]; - let result: i8x64 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m512i() - } + unsafe { transmute(vpacksswb(a.as_i16x32(), b.as_i16x32())) } } /// Convert packed signed 16-bit integers from a and b to packed 8-bit integers using signed saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6764,32 +6714,7 @@ pub fn _mm_maskz_packs_epi16(k: __mmask16, a: __m128i, b: __m128i) -> __m128i { #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackusdw))] pub fn _mm512_packus_epi32(a: __m512i, b: __m512i) -> __m512i { - unsafe { - let max = simd_splat(i32::from(u16::MAX)); - let min = simd_splat(i32::from(u16::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i32x16(), max), min) - .as_m512i() - .as_i16x32(); - let clamped_b = simd_imax(simd_imin(b.as_i32x16(), max), min) - .as_m512i() - .as_i16x32(); - - #[rustfmt::skip] - const IDXS: [u32; 32] = [ - 00, 02, 04, 06, - 32, 34, 36, 38, - 08, 10, 12, 14, - 40, 42, 44, 46, - 16, 18, 20, 22, - 48, 50, 52, 54, - 24, 26, 28, 30, - 56, 58, 60, 62, - ]; - let result: i16x32 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m512i() - } + unsafe { transmute(vpackusdw(a.as_i32x16(), b.as_i32x16())) } } /// Convert packed signed 32-bit integers from a and b to packed 16-bit integers using unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6884,32 +6809,7 @@ pub fn _mm_maskz_packus_epi32(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpackuswb))] pub fn _mm512_packus_epi16(a: __m512i, b: __m512i) -> __m512i { - unsafe { - let max = simd_splat(i16::from(u8::MAX)); - let min = simd_splat(i16::from(u8::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i16x32(), max), min) - .as_m512i() - .as_i8x64(); - let clamped_b = simd_imax(simd_imin(b.as_i16x32(), max), min) - .as_m512i() - .as_i8x64(); - - #[rustfmt::skip] - const IDXS: [u32; 64] = [ - 000, 002, 004, 006, 008, 010, 012, 014, - 064, 066, 068, 070, 072, 074, 076, 078, - 016, 018, 020, 022, 024, 026, 028, 030, - 080, 082, 084, 086, 088, 090, 092, 094, - 032, 034, 036, 038, 040, 042, 044, 046, - 096, 098, 100, 102, 104, 106, 108, 110, - 048, 050, 052, 054, 056, 058, 060, 062, - 112, 114, 116, 118, 120, 122, 124, 126, - ]; - let result: i8x64 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m512i() - } + unsafe { transmute(vpackuswb(a.as_i16x32(), b.as_i16x32())) } } /// Convert packed signed 16-bit integers from a and b to packed 8-bit integers using unsigned saturation, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -12706,6 +12606,15 @@ unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.pmaddubs.w.512"] fn vpmaddubsw(a: u8x64, b: i8x64) -> i16x32; + #[link_name = "llvm.x86.avx512.packssdw.512"] + fn vpackssdw(a: i32x16, b: i32x16) -> i16x32; + #[link_name = "llvm.x86.avx512.packsswb.512"] + fn vpacksswb(a: i16x32, b: i16x32) -> i8x64; + #[link_name = "llvm.x86.avx512.packusdw.512"] + fn vpackusdw(a: i32x16, b: i32x16) -> u16x32; + #[link_name = "llvm.x86.avx512.packuswb.512"] + fn vpackuswb(a: i16x32, b: i16x32) -> u8x64; + #[link_name = "llvm.x86.avx512.psll.w.512"] fn vpsllw(a: i16x32, count: i16x8) -> i16x32; diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index b719882c4864c..50e56005c9dff 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -1490,7 +1490,7 @@ pub const fn _mm_move_epi64(a: __m128i) -> __m128i { } } -/// Converts packed signed 16-bit integers from `a` and `b` to packed 8-bit integers +/// Converts packed 16-bit integers from `a` and `b` to packed 8-bit integers /// using signed saturation. /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi16) @@ -1499,27 +1499,10 @@ pub const fn _mm_move_epi64(a: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(packsswb))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { - let max = simd_splat(i16::from(i8::MAX)); - let min = simd_splat(i16::from(i8::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i16x8(), max), min) - .as_m128i() - .as_i8x16(); - let clamped_b = simd_imax(simd_imin(b.as_i16x8(), max), min) - .as_m128i() - .as_i8x16(); - - // Shuffle the low i8 of each i16 from two concatenated vectors into - // the low bits of the result register. - const IDXS: [u32; 16] = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]; - let result: i8x16 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m128i() - } + unsafe { transmute(packsswb(a.as_i16x8(), b.as_i16x8())) } } -/// Converts packed signed 32-bit integers from `a` and `b` to packed 16-bit integers +/// Converts packed 32-bit integers from `a` and `b` to packed 16-bit integers /// using signed saturation. /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32) @@ -1528,23 +1511,10 @@ pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(packssdw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i { - unsafe { - let max = simd_splat(i32::from(i16::MAX)); - let min = simd_splat(i32::from(i16::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i32x4(), max), min); - let clamped_b = simd_imax(simd_imin(b.as_i32x4(), max), min); - - let clamped_a: i16x4 = simd_cast(clamped_a); - let clamped_b: i16x4 = simd_cast(clamped_b); - - let a: i64 = transmute(clamped_a); - let b: i64 = transmute(clamped_b); - i64x2::new(a, b).as_m128i() - } + unsafe { transmute(packssdw(a.as_i32x4(), b.as_i32x4())) } } -/// Converts packed signed 16-bit integers from `a` and `b` to packed 8-bit integers +/// Converts packed 16-bit integers from `a` and `b` to packed 8-bit integers /// using unsigned saturation. /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16) @@ -1553,26 +1523,7 @@ pub fn _mm_packs_epi32(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(packuswb))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_packus_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { - let max = simd_splat(i16::from(u8::MAX)); - let min = simd_splat(i16::from(u8::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i16x8(), max), min) - .as_m128i() - .as_i8x16(); - let clamped_b = simd_imax(simd_imin(b.as_i16x8(), max), min) - .as_m128i() - .as_i8x16(); - - // Shuffle the low bytes of each i16 from two concatenated vectors into - // the low bits of the result register. - // Without `simd_shuffle`, this intrinsic will cause the AVX-512BW - // `_mm_mask_packus_epi16` and `_mm_maskz_packus_epi16` tests to fail. - const IDXS: [u32; 16] = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]; - let result: i8x16 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m128i() - } + unsafe { transmute(packuswb(a.as_i16x8(), b.as_i16x8())) } } /// Returns the `imm8` element of `a`. @@ -3272,6 +3223,12 @@ unsafe extern "unadjusted" { fn cvtps2dq(a: __m128) -> i32x4; #[link_name = "llvm.x86.sse2.maskmov.dqu"] fn maskmovdqu(a: i8x16, mask: i8x16, mem_addr: *mut i8); + #[link_name = "llvm.x86.sse2.packsswb.128"] + fn packsswb(a: i16x8, b: i16x8) -> i8x16; + #[link_name = "llvm.x86.sse2.packssdw.128"] + fn packssdw(a: i32x4, b: i32x4) -> i16x8; + #[link_name = "llvm.x86.sse2.packuswb.128"] + fn packuswb(a: i16x8, b: i16x8) -> u8x16; #[link_name = "llvm.x86.sse2.max.sd"] fn maxsd(a: __m128d, b: __m128d) -> __m128d; #[link_name = "llvm.x86.sse2.max.pd"] diff --git a/library/stdarch/crates/core_arch/src/x86/sse41.rs b/library/stdarch/crates/core_arch/src/x86/sse41.rs index 38e7ab39c4dac..063de0d592a22 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse41.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse41.rs @@ -418,7 +418,7 @@ pub const fn _mm_min_epu32(a: __m128i, b: __m128i) -> __m128i { unsafe { simd_imin(a.as_u32x4(), b.as_u32x4()).as_m128i() } } -/// Converts packed signed 32-bit integers from `a` and `b` to packed 16-bit integers +/// Converts packed 32-bit integers from `a` and `b` to packed 16-bit integers /// using unsigned saturation /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32) @@ -427,24 +427,7 @@ pub const fn _mm_min_epu32(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(packusdw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_packus_epi32(a: __m128i, b: __m128i) -> __m128i { - unsafe { - let max = simd_splat(i32::from(u16::MAX)); - let min = simd_splat(i32::from(u16::MIN)); - - let clamped_a = simd_imax(simd_imin(a.as_i32x4(), max), min) - .as_m128i() - .as_i16x8(); - let clamped_b = simd_imax(simd_imin(b.as_i32x4(), max), min) - .as_m128i() - .as_i16x8(); - - // Shuffle the low u16 of each i32 from two concatenated vectors into - // the low bits of the result register. - const IDXS: [u32; 8] = [0, 2, 4, 6, 8, 10, 12, 14]; - let result: i16x8 = simd_shuffle!(clamped_a, clamped_b, IDXS); - - result.as_m128i() - } + unsafe { transmute(packusdw(a.as_i32x4(), b.as_i32x4())) } } /// Compares packed 64-bit integers in `a` and `b` for equality @@ -1183,6 +1166,8 @@ pub unsafe fn _mm_stream_load_si128(mem_addr: *const __m128i) -> __m128i { unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse41.insertps"] fn insertps(a: __m128, b: __m128, imm8: u8) -> __m128; + #[link_name = "llvm.x86.sse41.packusdw"] + fn packusdw(a: i32x4, b: i32x4) -> u16x8; #[link_name = "llvm.x86.sse41.dppd"] fn dppd(a: __m128d, b: __m128d, imm8: u8) -> __m128d; #[link_name = "llvm.x86.sse41.dpps"] From 1358f54aebe02d8a2723e602f0d0b56527b14e93 Mon Sep 17 00:00:00 2001 From: Jonathan Keller Date: Tue, 25 Aug 2026 11:22:24 -0700 Subject: [PATCH 04/13] Check to ensure we're running against the correct LLVM version (cherry picked from commit dbea26933ed18a856c612a2157e8cb3babb88c37) --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 ++ compiler/rustc_codegen_llvm/src/llvm_util.rs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 1a60b59a93525..f575f37440f54 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -894,6 +894,8 @@ unsafe extern "C" { SLen: c_uint, ) -> MetadataKindId; + pub(crate) fn LLVMGetVersion(major: &mut c_uint, minor: &mut c_uint, patch: &mut c_uint); + pub(crate) fn LLVMDisposeTargetMachine(T: ptr::NonNull); // Create modules. diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 298b58dd0007f..64b166113e42d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -48,6 +48,24 @@ unsafe fn configure_llvm(sess: &Session) { let mut llvm_c_strs = Vec::with_capacity(n_args + 1); let mut llvm_args = Vec::with_capacity(n_args + 1); + // Check to ensure we're running against the correct LLVM version. + unsafe { + let mut llvm_major = 0; + let mut llvm_minor = 0; + let mut llvm_patch = 0; + llvm::LLVMGetVersion(&mut llvm_major, &mut llvm_minor, &mut llvm_patch); + let expected_version = llvm::LLVMRustVersionMajor(); + if llvm_major != expected_version { + panic!( + concat!( + "LLVM version mismatch: this compiler was built for LLVM {}, ", + "but LLVM {}.{}.{} is loaded" + ), + expected_version, llvm_major, llvm_minor, llvm_patch + ); + } + } + unsafe { llvm::LLVMRustInstallErrorHandlers(); } From 9e0ae0cffdf959ac6bfdd39b48cbfa79019b77b1 Mon Sep 17 00:00:00 2001 From: Jonathan Keller Date: Tue, 25 Aug 2026 11:46:16 -0700 Subject: [PATCH 05/13] Look up and print path to wrong LLVM version (cherry picked from commit 5841e102da7f55ae38a35aaaa8ab3dd4a4b29d0d) --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 11 +- compiler/rustc_session/src/filesearch.rs | 153 ++++++++++--------- 2 files changed, 86 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 64b166113e42d..9819699ca5228 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -59,9 +59,16 @@ unsafe fn configure_llvm(sess: &Session) { panic!( concat!( "LLVM version mismatch: this compiler was built for LLVM {}, ", - "but LLVM {}.{}.{} is loaded" + "but LLVM {}.{}.{} was found{}" ), - expected_version, llvm_major, llvm_minor, llvm_patch + expected_version, + llvm_major, + llvm_minor, + llvm_patch, + match rustc_session::filesearch::dll_path(llvm::LLVMGetVersion as *mut _) { + Ok(path) => format!(" at {}", path.display()), + Err(_) => String::new(), + } ); } } diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index d88fed2f84ab8..6ec1466500a86 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -146,86 +146,78 @@ pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf { sysroot.join(rustlib_path).join("bin") } +/// Attempts to find the path to the dynamic library containing a function. +/// +/// SAFETY: `function` must be a valid pointer to some function. #[cfg(unix)] -fn current_dll_path() -> Result { - use std::sync::OnceLock; +pub unsafe fn dll_path(function: *mut std::ffi::c_void) -> Result { + use std::ffi::{CStr, OsStr}; + use std::os::unix::prelude::*; - // This is somewhat expensive relative to other work when compiling `fn main() {}` as `dladdr` - // needs to iterate over the symbol table of librustc_driver.so until it finds a match. - // As such cache this to avoid recomputing if we try to get the sysroot in multiple places. - static CURRENT_DLL_PATH: OnceLock> = OnceLock::new(); - CURRENT_DLL_PATH - .get_or_init(|| { - use std::ffi::{CStr, OsStr}; - use std::os::unix::prelude::*; - - #[cfg(not(target_os = "aix"))] - unsafe { - let addr = current_dll_path as fn() -> Result as *mut _; - let mut info = std::mem::zeroed(); - if libc::dladdr(addr, &mut info) == 0 { - return Err("dladdr failed".into()); + #[cfg(not(target_os = "aix"))] + unsafe { + let mut info = std::mem::zeroed(); + if libc::dladdr(function, &mut info) == 0 { + return Err("dladdr failed".into()); + } + #[cfg(target_os = "cygwin")] + let fname_ptr = info.dli_fname.as_ptr(); + #[cfg(not(target_os = "cygwin"))] + let fname_ptr = { + assert!(!info.dli_fname.is_null(), "dli_fname cannot be null"); + info.dli_fname + }; + let bytes = CStr::from_ptr(fname_ptr).to_bytes(); + let os = OsStr::from_bytes(bytes); + try_canonicalize(Path::new(os)).map_err(|e| e.to_string()) + } + + #[cfg(target_os = "aix")] + unsafe { + // On AIX, the symbol references a function descriptor. + // A function descriptor is consisted of (See https://reviews.llvm.org/D62532) + // * The address of the entry point of the function. + // * The TOC base address for the function. + // * The environment pointer. + // The function descriptor is in the data section. + let addr = function as u64; + let mut buffer = vec![std::mem::zeroed::(); 64]; + loop { + if libc::loadquery( + libc::L_GETINFO, + buffer.as_mut_ptr() as *mut libc::c_void, + (size_of::() * buffer.len()) as u32, + ) >= 0 + { + break; + } else { + if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM { + return Err("loadquery failed".into()); } - #[cfg(target_os = "cygwin")] - let fname_ptr = info.dli_fname.as_ptr(); - #[cfg(not(target_os = "cygwin"))] - let fname_ptr = { - assert!(!info.dli_fname.is_null(), "dli_fname cannot be null"); - info.dli_fname - }; - let bytes = CStr::from_ptr(fname_ptr).to_bytes(); + buffer.resize(buffer.len() * 2, std::mem::zeroed::()); + } + } + let mut current = buffer.as_mut_ptr() as *mut libc::ld_info; + loop { + let data_base = (*current).ldinfo_dataorg as u64; + let data_end = data_base + (*current).ldinfo_datasize; + if (data_base..data_end).contains(&addr) { + let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes(); let os = OsStr::from_bytes(bytes); - try_canonicalize(Path::new(os)).map_err(|e| e.to_string()) + return try_canonicalize(Path::new(os)).map_err(|e| e.to_string()); } - - #[cfg(target_os = "aix")] - unsafe { - // On AIX, the symbol `current_dll_path` references a function descriptor. - // A function descriptor is consisted of (See https://reviews.llvm.org/D62532) - // * The address of the entry point of the function. - // * The TOC base address for the function. - // * The environment pointer. - // The function descriptor is in the data section. - let addr = current_dll_path as u64; - let mut buffer = vec![std::mem::zeroed::(); 64]; - loop { - if libc::loadquery( - libc::L_GETINFO, - buffer.as_mut_ptr() as *mut libc::c_void, - (size_of::() * buffer.len()) as u32, - ) >= 0 - { - break; - } else { - if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM { - return Err("loadquery failed".into()); - } - buffer.resize(buffer.len() * 2, std::mem::zeroed::()); - } - } - let mut current = buffer.as_mut_ptr() as *mut libc::ld_info; - loop { - let data_base = (*current).ldinfo_dataorg as u64; - let data_end = data_base + (*current).ldinfo_datasize; - if (data_base..data_end).contains(&addr) { - let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes(); - let os = OsStr::from_bytes(bytes); - return try_canonicalize(Path::new(os)).map_err(|e| e.to_string()); - } - if (*current).ldinfo_next == 0 { - break; - } - current = (current as *mut i8).offset((*current).ldinfo_next as isize) - as *mut libc::ld_info; - } - return Err(format!("current dll's address {} is not in the load map", addr)); + if (*current).ldinfo_next == 0 { + break; } - }) - .clone() + current = + (current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info; + } + return Err(format!("current dll's address {} is not in the load map", addr)); + } } #[cfg(windows)] -fn current_dll_path() -> Result { +pub unsafe fn dll_path(function: *mut std::ffi::c_void) -> Result { use std::ffi::OsString; use std::io; use std::os::windows::prelude::*; @@ -240,10 +232,7 @@ fn current_dll_path() -> Result { unsafe { GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - PCWSTR( - current_dll_path as fn() -> Result - as *mut u16, - ), + PCWSTR(function as *mut u16), &mut module, ) } @@ -269,8 +258,20 @@ fn current_dll_path() -> Result { } #[cfg(target_os = "wasi")] +pub unsafe fn dll_path(function: *mut std::ffi::c_void) -> Result { + Err("dll_path is not supported on WASI".to_string()) +} + fn current_dll_path() -> Result { - Err("current_dll_path is not supported on WASI".to_string()) + use std::sync::OnceLock; + + // This is somewhat expensive relative to other work when compiling `fn main() {}` as `dladdr` + // needs to iterate over the symbol table of librustc_driver.so until it finds a match. + // As such cache this to avoid recomputing if we try to get the sysroot in multiple places. + static CURRENT_DLL_PATH: OnceLock> = OnceLock::new(); + CURRENT_DLL_PATH + .get_or_init(|| unsafe { dll_path(current_dll_path as fn() -> _ as *mut _) }) + .clone() } /// This function checks if sysroot is found using env::args().next(), and if it From 464944673c0c0e69175ea88286b7ec2e5d5a303e Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 30 Aug 2026 20:47:08 -0400 Subject: [PATCH 06/13] Make the LLVM version mismatch ICE a fatal error (cherry picked from commit 1d7375898dacaaeed8046891066b0e2b58f488c4) --- compiler/rustc_codegen_llvm/src/diagnostics.rs | 14 +++++++++++++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 13 +++++-------- compiler/rustc_macros/src/diagnostics/message.rs | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 54f8ffbb881da..fb43b36fe39b9 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -1,4 +1,4 @@ -use std::ffi::CString; +use std::ffi::{CString, c_uint}; use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; @@ -265,3 +265,15 @@ pub(crate) struct IntrinsicWrongArch<'a> { pub(crate) struct UnknownLlvmTargetFeaturePrefix<'a> { pub feature: &'a str, } + +#[derive(Diagnostic)] +#[diag( + "LLVM version mismatch: this compiler was built for LLVM {$expected_version}, but LLVM {$llvm_major}.{$llvm_minor}.{$llvm_patch} was found{$dll_loc}" +)] +pub(crate) struct LlvmVersionMismatch<'a> { + pub expected_version: c_uint, + pub llvm_major: c_uint, + pub llvm_minor: c_uint, + pub llvm_patch: c_uint, + pub dll_loc: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9819699ca5228..82ddcca3e1530 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -56,20 +56,17 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMGetVersion(&mut llvm_major, &mut llvm_minor, &mut llvm_patch); let expected_version = llvm::LLVMRustVersionMajor(); if llvm_major != expected_version { - panic!( - concat!( - "LLVM version mismatch: this compiler was built for LLVM {}, ", - "but LLVM {}.{}.{} was found{}" - ), + sess.dcx().emit_fatal(diagnostics::LlvmVersionMismatch { expected_version, llvm_major, llvm_minor, llvm_patch, - match rustc_session::filesearch::dll_path(llvm::LLVMGetVersion as *mut _) { + dll_loc: &match rustc_session::filesearch::dll_path(llvm::LLVMGetVersion as *mut _) + { Ok(path) => format!(" at {}", path.display()), Err(_) => String::new(), - } - ); + }, + }) } } diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 63561e409b0ae..8eff9a4fa9e8a 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -133,6 +133,7 @@ const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[ "Cargo", "Ferris", "GCC", + "LLVM", "MIR", "NaNs", "OK", From dfb782be28342163e50d8e11faa89daaa4a67304 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 28 Aug 2026 15:58:08 +0200 Subject: [PATCH 07/13] Add regression test for "use of an internal attribute" (cherry picked from commit 3ff39765b2649118d8a55d8cee79f0152ded6c53) --- tests/ui/proc-macro/auxiliary/test-re-emit.rs | 8 ++++++++ tests/ui/proc-macro/test-re-emit.rs | 15 +++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/ui/proc-macro/auxiliary/test-re-emit.rs create mode 100644 tests/ui/proc-macro/test-re-emit.rs diff --git a/tests/ui/proc-macro/auxiliary/test-re-emit.rs b/tests/ui/proc-macro/auxiliary/test-re-emit.rs new file mode 100644 index 0000000000000..4b500c4a66166 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/test-re-emit.rs @@ -0,0 +1,8 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn remove_span(_attr: TokenStream, item: TokenStream) -> TokenStream { + // `.to_string().parse()` will lose the span of the token stream + item.to_string().parse().unwrap() +} diff --git a/tests/ui/proc-macro/test-re-emit.rs b/tests/ui/proc-macro/test-re-emit.rs new file mode 100644 index 0000000000000..c01df98e79a6e --- /dev/null +++ b/tests/ui/proc-macro/test-re-emit.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ proc-macro: test-re-emit.rs +//@ compile-flags: --test +// Test that we can pass a test through a proc macro that removes the span of the item +// Regression test for https://github.com/rust-lang/rust/issues/161917 + +#[test] +#[test_re_emit::remove_span] +fn meow1() {} + +#[test_re_emit::remove_span] +#[test] +fn meow2() {} + +fn main() {} From 5f9fe9ed728767536031d5342d03c8857e596eeb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 28 Aug 2026 16:11:46 +0200 Subject: [PATCH 08/13] Add regression test for "expected item after attributes" (cherry picked from commit ca095daf5fb08010cf044a4253d8d74586f9a354) --- .../auxiliary/test-count-attributes.rs | 23 ++++++++++++++ tests/ui/proc-macro/test-count-attributes.rs | 30 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/ui/proc-macro/auxiliary/test-count-attributes.rs create mode 100644 tests/ui/proc-macro/test-count-attributes.rs diff --git a/tests/ui/proc-macro/auxiliary/test-count-attributes.rs b/tests/ui/proc-macro/auxiliary/test-count-attributes.rs new file mode 100644 index 0000000000000..c5658f445df2d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/test-count-attributes.rs @@ -0,0 +1,23 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn assert_no_attributes(_attr: TokenStream, item: TokenStream) -> TokenStream { + // This will count the "attributes" (in reality the number of hash symbols) on the item. + assert_eq!(item.to_string().chars().filter(|c| *c == '#').count(), 0); + item +} + +#[proc_macro_attribute] +pub fn assert_one_attribute(_attr: TokenStream, item: TokenStream) -> TokenStream { + // This will count the "attributes" (in reality the number of hash symbols) on the item. + assert_eq!(item.to_string().chars().filter(|c| *c == '#').count(), 1); + item +} + +#[proc_macro_attribute] +pub fn assert_two_attributes(_attr: TokenStream, item: TokenStream) -> TokenStream { + // This will count the "attributes" (in reality the number of hash symbols) on the item. + assert_eq!(item.to_string().chars().filter(|c| *c == '#').count(), 2); + item +} diff --git a/tests/ui/proc-macro/test-count-attributes.rs b/tests/ui/proc-macro/test-count-attributes.rs new file mode 100644 index 0000000000000..930e69cc6381f --- /dev/null +++ b/tests/ui/proc-macro/test-count-attributes.rs @@ -0,0 +1,30 @@ +//@ check-pass +//@ proc-macro: test-count-attributes.rs +//@ compile-flags: --test +// Tests whether attributes on tests can be observed by proc macros +// Regression test for https://github.com/rust-lang/rust/issues/161920 + +#[test] +#[test_count_attributes::assert_no_attributes] +fn meow1() {} + +#[test_count_attributes::assert_one_attribute] +#[test] +fn meow2() {} + +#[test] +#[should_panic] +#[test_count_attributes::assert_one_attribute] +fn meow3() {} + +#[test] +#[test_count_attributes::assert_one_attribute] +#[should_panic] +fn meow4() {} + +#[test_count_attributes::assert_two_attributes] +#[test] +#[should_panic] +fn meow5() {} + +fn main() {} From 840adec7f082a0f2c4febdba6614472fa80cdcd6 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 30 Aug 2026 19:04:16 +0200 Subject: [PATCH 09/13] Add regression test for "use of an internal attribute" with a `macro_rules!` macro (cherry picked from commit 58f825e7e69b482da18a8ea83cb3f8f43415f996) --- tests/ui/macros/parse-test.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/ui/macros/parse-test.rs diff --git a/tests/ui/macros/parse-test.rs b/tests/ui/macros/parse-test.rs new file mode 100644 index 0000000000000..a60d196805cd3 --- /dev/null +++ b/tests/ui/macros/parse-test.rs @@ -0,0 +1,18 @@ +//@ check-pass +//@ compile-flags: --test +// Test that we can pass a test through a macro_rules! macro that removes the span of the item +// Regression test for https://github.com/rust-lang/rust/issues/161917 +#![feature(macro_attr)] + +macro_rules! ohno { + attr() { $(#[$a:meta])* fn $name:ident () $body: block } => { + $(#[$a])* + fn $name () $body + } +} + +#[test] +#[ohno] +fn my_test() {} + +fn main() {} From fdff7999bc9d2008c75b9e636adc811f7848b6b3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 28 Aug 2026 15:04:51 +0200 Subject: [PATCH 10/13] Revert "Add `rustc_test_entrypoint_marker`" (cherry picked from commit 9b70ab051c8a6937e6e86b1bdc715d6896c2d18d) --- compiler/rustc_attr_ir/src/data_structures.rs | 3 - .../rustc_attr_ir/src/encode_cross_crate.rs | 1 - .../src/attributes/test_attrs.rs | 11 --- compiler/rustc_attr_parsing/src/context.rs | 1 - compiler/rustc_builtin_macros/src/test.rs | 9 -- compiler/rustc_feature/src/builtin_attrs.rs | 1 - compiler/rustc_passes/src/check_attr.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 - tests/pretty/tests-are-sorted.pp | 3 - tests/ui-fulldeps/test_entrypoint_attrs.rs | 84 ------------------- 10 files changed, 115 deletions(-) delete mode 100644 tests/ui-fulldeps/test_entrypoint_attrs.rs diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 81887e0176ee7..581275d4de43b 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1646,9 +1646,6 @@ pub enum AttributeKind { /// Represents `#[rustc_strict_coherence]`. RustcStrictCoherence(Span), - /// Represents `#[rustc_test_entrypoint_marker]` - RustcTestEntrypointMarker, - /// Represents `#[rustc_test_marker]` RustcTestMarker(Symbol), diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index 6a9f37f80868a..3d08434636e49 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -193,7 +193,6 @@ impl AttributeKind { RustcSpecializationTrait => No, RustcStdInternalSymbol => No, RustcStrictCoherence(..) => Yes, - RustcTestEntrypointMarker => No, RustcTestMarker(..) => No, RustcThenThisWouldNeed(..) => No, RustcTrivialFieldReads => Yes, diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 22dd77ce45737..54c50b5b3ff1f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -214,14 +214,3 @@ impl SingleAttributeParser for RustcTestMarkerParser { Some(AttributeKind::RustcTestMarker(value_str)) } } - -pub(crate) struct RustcTestEntrypointMarkerParser; - -impl NoArgsAttributeParser for RustcTestEntrypointMarkerParser { - const PATH: &[Symbol] = &[sym::rustc_test_entrypoint_marker]; - const ALLOWED_TARGETS: AllowedTargets<'_> = - AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::Closure)]); - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const STABILITY: AttributeStability = unstable!(rustc_attrs); - const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTestEntrypointMarker; -} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 73195c7b77b10..f98b36f5873b7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -354,7 +354,6 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 9839de9ce0560..01923a647d87e 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -23,9 +23,6 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; /// /// We mark item with an inert attribute "rustc_test_marker" which the test generation /// logic will pick up on. -/// -/// The test function also gains a `#[rustc_test_entrypoint_marker]` attribute for tools to pick up -/// on. This behavior is *unstable*. pub(crate) fn expand_test_case( ecx: &mut ExtCtxt<'_>, attr_sp: Span, @@ -380,12 +377,6 @@ pub(crate) fn expand_test_or_bench( let test_extern = cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)); - let item = { - let mut item = item; - item.attrs.push(cx.attr_word(sym::rustc_test_entrypoint_marker, attr_sp)); - item - }; - debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); if is_stmt { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index bc6f87a2a7f17..9db0f95818e7d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -365,7 +365,6 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ sym::rustc_paren_sugar, sym::rustc_inherit_overflow_checks, sym::rustc_reservation_impl, - sym::rustc_test_entrypoint_marker, sym::rustc_test_marker, sym::rustc_allow_lifetime_dependent_specialization, sym::rustc_specialization_trait, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e035e16cabb91..1d40b277e69a6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -390,7 +390,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcSpecializationTrait => (), AttributeKind::RustcStdInternalSymbol => (), AttributeKind::RustcStrictCoherence(..) => (), - AttributeKind::RustcTestEntrypointMarker => (), AttributeKind::RustcTestMarker(..) => (), AttributeKind::RustcThenThisWouldNeed(..) => (), AttributeKind::RustcTrivialFieldReads => (), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 45df107bf7469..5ca437706d580 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1872,7 +1872,6 @@ symbols! { rustc_splat, rustc_std_internal_symbol, rustc_strict_coherence, - rustc_test_entrypoint_marker, rustc_test_marker, rustc_then_this_would_need, rustc_trivial_field_reads, diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index f49c79f31a5ec..43f9838e68ce9 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -30,7 +30,6 @@ testfn: test::StaticTestFn(#[coverage(off)] || test::assert_test_result(m_test())), }; -#[rustc_test_entrypoint_marker] fn m_test() {} extern crate test; @@ -56,7 +55,6 @@ test::assert_test_result(z_test())), }; #[ignore = "not yet implemented"] -#[rustc_test_entrypoint_marker] fn z_test() {} extern crate test; @@ -81,7 +79,6 @@ testfn: test::StaticTestFn(#[coverage(off)] || test::assert_test_result(a_test())), }; -#[rustc_test_entrypoint_marker] fn a_test() {} #[rustc_main] #[coverage(off)] diff --git a/tests/ui-fulldeps/test_entrypoint_attrs.rs b/tests/ui-fulldeps/test_entrypoint_attrs.rs deleted file mode 100644 index dac7406337c57..0000000000000 --- a/tests/ui-fulldeps/test_entrypoint_attrs.rs +++ /dev/null @@ -1,84 +0,0 @@ -//@ run-pass -//@ ignore-cross-compile -//@ ignore-remote -//@ edition: 2024 -//@ ignore-stage1 -//! Uses a rustc driver to check that test entrypoints get a `#[rustc_test_entrypoint_marker]` -//! and can be found using that attribute in rustc drivers (the main use for this attribute). - -#![feature(rustc_private)] - -extern crate rustc_driver; -extern crate rustc_interface; -extern crate rustc_middle; -#[macro_use] -extern crate rustc_hir; - -use interface::Compiler; -use rustc_driver::Compilation; -use rustc_interface::interface; -use rustc_middle::ty::TyCtxt; -use std::io::Write; - -const CRATE_NAME: &str = "input"; - -struct TestAttr { - expected_tests: usize, -} - -impl rustc_driver::Callbacks for TestAttr { - fn after_analysis<'tcx>(&mut self, _compiler: &Compiler, tcx: TyCtxt<'tcx>) -> Compilation { - let mut tests = Vec::new(); - for did in tcx.hir_crate_items(()).definitions() { - if find_attr!(tcx, did, RustcTestEntrypointMarker) { - tests.push(did); - } - } - - // the file contains one test, so we should find one entrypoint marker. - assert_eq!(tests.len(), self.expected_tests); - - Compilation::Stop - } -} - -fn count_tests(src: &str, expected_tests: usize) { - let path = "test_input.rs"; - let mut file = std::fs::File::create(path).unwrap(); - file.write_all(src.as_bytes()).unwrap(); - - let args = [ - "rustc".to_string(), - "--test".to_string(), - "--crate-type=lib".to_string(), - "--crate-name".to_string(), - CRATE_NAME.to_string(), - path.to_string(), - ]; - rustc_driver::catch_fatal_errors(|| -> interface::Result<()> { - rustc_driver::run_compiler(&args, &mut TestAttr { expected_tests }); - Ok(()) - }) - .unwrap() - .unwrap(); -} - -fn main() { - count_tests( - r#" - #[test] - fn meow() {{ }} - "#, - 1, - ); - count_tests( - r#" - #[test] - fn one() {{ }} - - #[test] - fn two() {{ }} - "#, - 2, - ); -} From 27e3f84609b5089c8d361f2dc35a79f7c048032c Mon Sep 17 00:00:00 2001 From: Yukang Date: Mon, 31 Aug 2026 22:45:49 +0800 Subject: [PATCH 11/13] Fix ICE of getting name from RPITIT (cherry picked from commit 2da32405305a277a14178b259604f518ce31276a) --- .../src/error_reporting/infer/mod.rs | 7 +++- ...mismatch-missing-item-name-issue-161915.rs | 17 ++++++++++ ...atch-missing-item-name-issue-161915.stderr | 34 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.rs create mode 100644 tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 1210a3ef57e32..35449284b5093 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1374,7 +1374,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (ty::Alias(kind1, alias1), ty::Alias(kind2, alias2)) if kind1 == kind2 => { let mut values = (DiagStyledString::new(), DiagStyledString::new()); match (alias1.kind, alias2.kind) { - (ty::Projection { def_id: def_id1 }, ty::Projection { def_id: def_id2 }) => { + (ty::Projection { def_id: def_id1 }, ty::Projection { def_id: def_id2 }) + // RPITIT projections use anonymous associated type and have no item name, + // so it will be ICE from call of `tcx.item_name(def_id)` below, issue #161915. + if !self.tcx.is_impl_trait_in_trait(def_id1) + && !self.tcx.is_impl_trait_in_trait(def_id2) => + { // `::Name` values.0.push_normal("<"); values.1.push_normal("<"); diff --git a/tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.rs b/tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.rs new file mode 100644 index 0000000000000..2f28b14d74677 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.rs @@ -0,0 +1,17 @@ +//! Regression test for . +//! Mismatched RPITIT projections should produce E0308 instead of an ICE. + +trait Parameter { + fn create() -> impl Form; +} + +trait Form {} + +fn forms_at_phase() -> impl Form { + match true { + true => T::create(), + false => U::create(), //~ ERROR `match` arms have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.stderr b/tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.stderr new file mode 100644 index 0000000000000..7b8f6e438c456 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-mismatch-missing-item-name-issue-161915.stderr @@ -0,0 +1,34 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/rpitit-mismatch-missing-item-name-issue-161915.rs:13:18 + | +LL | fn forms_at_phase() -> impl Form { + | - - found type parameter + | | + | expected type parameter +LL | / match true { +LL | | true => T::create(), + | | ----------- this is found to be of type `impl Form` +LL | | false => U::create(), + | | ^^^^^^^^^^^ expected type parameter `T`, found type parameter `U` +LL | | } + | |_____- `match` arms have incompatible types + | + = note: expected associated type `impl Form` (type parameter `T`) + found associated type `impl Form` (type parameter `U`) + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + = note: an associated type was expected, but a different one was found +help: you could change the return type to be a boxed trait object + | +LL - fn forms_at_phase() -> impl Form { +LL + fn forms_at_phase() -> Box { + | +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ true => Box::new(T::create()), +LL ~ false => Box::new(U::create()), + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 4e87c0be072c0644a4bdafed834830f4e3df8f97 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 1 Sep 2026 17:12:16 +0200 Subject: [PATCH 12/13] Update LLVM submodule (cherry picked from commit 8e6d69e8222ad61d0a3f8a1234b83cebc5eb720f) --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 21cf284327989..76a3a9d0075fe 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 21cf28432798952d942bacc6bcee3a328faa3638 +Subproject commit 76a3a9d0075fe0df4bb57160372700006e3d0b2b From e6674777a9ba61edd28247ca8251df6c3a87d982 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Sep 2026 10:55:35 +1000 Subject: [PATCH 13/13] Revert "Implement Debug for C-like enums with a concatenated string" From #155452. Fixes #162124. (cherry picked from commit f91c12f29eae6b63de9780d49d873425a832ad1a) --- .../src/deriving/debug.rs | 130 +----------------- compiler/rustc_span/src/symbol.rs | 1 - library/core/src/fmt/mod.rs | 15 -- tests/ui/derives/deriving-all-codegen.rs | 23 ---- tests/ui/derives/deriving-all-codegen.stdout | 43 ------ .../hygiene/unpretty-debug-lifetimes.stdout | 4 +- 6 files changed, 4 insertions(+), 212 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index c41a4e4fd6b8d..2436800d0099d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -1,4 +1,4 @@ -use rustc_ast::{self as ast, EnumDef, ExprKind, MetaItem, Safety, TyKind, token}; +use rustc_ast::{self as ast, EnumDef, MetaItem, Safety}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_session::config::FmtDebug; use rustc_span::{Ident, Span, Symbol, sym}; @@ -230,10 +230,6 @@ fn show_fieldless_enum( substr: &Substructure<'_>, ) -> BlockOrExpr { let fmt = substr.nonselflike_args[0].clone(); - if let Some((stmts, expr)) = show_fieldless_enum_concat_str(cx, span, def, fmt.clone()) { - return BlockOrExpr::new_mixed(stmts, Some(expr)); - } - let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); let arms = def .variants .iter() @@ -254,128 +250,6 @@ fn show_fieldless_enum( }) .collect::>(); let name = cx.expr_match(span, cx.expr_self(span), arms); + let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name])) } - -/// Special case for fieldless enums with no discriminants. Builds -/// ```text -/// impl ::core::fmt::Debug for A { -/// fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { -/// static __NAMES: &str = "ABBBCC"; -/// static __OFFSET: [usize; 4] =[0, 1, 4, 6]; -/// let __d = ::core::intrinsics::discriminant_value(self) as usize; -/// ::core::fmt::Formatter::debug_c_like_enums_write_str(f, __NAMES, &__OFFSET, __d) -/// } -/// } -/// ``` -fn show_fieldless_enum_concat_str( - cx: &ExtCtxt<'_>, - span: Span, - def: &EnumDef, - fmt: Box, -) -> Option<(ThinVec, Box)> { - // Minimum variants count where this optimization starts to pay off. - // See https://github.com/rust-lang/rust/pull/155452 for more details. - const THRESHOLD: usize = 10; - let variants_count = def.variants.len(); - if variants_count < THRESHOLD { - return None; - } - - let variant_names = def - .variants - .iter() - .map(|v| v.disr_expr.is_none().then_some(v.ident.name.as_str())) - .collect::>>()?; - - let total_bytes: usize = variant_names.iter().map(|n| n.len()).sum(); - let mut concatenated_names = String::with_capacity(total_bytes); - let mut offset_indices = Vec::with_capacity(variant_names.len() + 1); - offset_indices.push(0); - - for name in variant_names.iter() { - concatenated_names.push_str(name); - offset_indices.push(concatenated_names.len()); - } - - // Create the constant concatenated string - let names_ident = Ident::from_str_and_span("__NAMES", span); - let str_ty = cx.ty( - span, - TyKind::Ref( - None, - ast::MutTy { - ty: cx.ty( - span, - TyKind::Path(None, ast::Path::from_ident(Ident::new(sym::str, span))), - ), - mutbl: ast::Mutability::Not, - }, - ), - ); - let names_str_body = cx.expr_str(span, Symbol::intern(&concatenated_names)); - let names_static_item = - cx.item_static(span, names_ident, str_ty, ast::Mutability::Not, names_str_body); - - // Create the constant offset array - let offset_ident = Ident::from_str_and_span("__OFFSET", span); - let offset_index_exprs = - offset_indices.iter().map(|s| cx.expr_usize(span, *s)).collect::>(); - let starts_array_body = cx.expr_array(span, offset_index_exprs); - let usize_ty = - cx.ty(span, TyKind::Path(None, ast::Path::from_ident(Ident::new(sym::usize, span)))); - let offset_array_len_expr = cx.anon_const( - span, - ExprKind::Lit(token::Lit::new( - token::LitKind::Integer, - Symbol::intern(&(variants_count + 1).to_string()), - None, - )), - ); - let offset_static_item = cx.item_static( - span, - offset_ident, - cx.ty(span, TyKind::Array(usize_ty, offset_array_len_expr)), - ast::Mutability::Not, - starts_array_body, - ); - - // let __d = ::core::intrinsics::discriminant_value(self) as usize; - let discriminant_ident = Ident::from_str_and_span("__d", span); - let discriminant_intrinsic_path = cx.std_path(&[sym::intrinsics, sym::discriminant_value]); - let discriminant_cast_expr = cx.expr( - span, - ast::ExprKind::Cast( - cx.expr_call_global(span, discriminant_intrinsic_path, thin_vec![cx.expr_self(span)]), - cx.ty_path(ast::Path::from_ident(Ident::new(sym::usize, span))), - ), - ); - let discriminant_let_stmt = - cx.stmt_let(span, false, discriminant_ident, discriminant_cast_expr); - - // __d expression - let discriminant_expr = cx.expr_ident(span, discriminant_ident); - - // __NAMES expression - let names_expr = cx.expr_ident(span, names_ident); - - // &__OFFSET expression - let offset_ref_expr = cx.expr_addr_of(span, cx.expr_ident(span, offset_ident)); - - // ::core::fmt::Formatter::debug_c_like_enum_write_str(f, __NAMES, &__OFFSET, __d) - let fn_path = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_c_like_enum_write_str]); - let call_expr = cx.expr_call_global( - span, - fn_path, - thin_vec![fmt, names_expr, offset_ref_expr, discriminant_expr], - ); - - Some(( - thin_vec![ - cx.stmt_item(span, names_static_item), - cx.stmt_item(span, offset_static_item), - discriminant_let_stmt, - ], - call_expr, - )) -} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5ca437706d580..e0f1a2e26b553 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -776,7 +776,6 @@ symbols! { debug_assert_macro, debug_assert_ne_macro, debug_assertions, - debug_c_like_enum_write_str, debug_struct_fields_finish, debug_tuple_fields_finish, debugger_visualizer, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 47886aa7165d9..03ab0cc499a8c 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2577,21 +2577,6 @@ impl<'a> Formatter<'a> { builder.finish() } - /// Shrinks `derive(Debug)` code, for faster compilation and smaller binaries. - /// For C-like enums with concatenated variant name strings. - #[doc(hidden)] - #[unstable(feature = "fmt_helpers_for_derive", issue = "none")] - pub fn debug_c_like_enum_write_str<'b>( - &'b mut self, - names: &str, - offset: &[usize], - discr: usize, - ) -> Result { - let start = offset[discr]; - let end = offset[discr + 1]; - self.write_str(&names[start..end]) - } - /// Creates a `DebugTuple` builder designed to assist with creation of /// `fmt::Debug` implementations for tuple structs. /// diff --git a/tests/ui/derives/deriving-all-codegen.rs b/tests/ui/derives/deriving-all-codegen.rs index a5342c73a5962..343d4095da470 100644 --- a/tests/ui/derives/deriving-all-codegen.rs +++ b/tests/ui/derives/deriving-all-codegen.rs @@ -154,29 +154,6 @@ enum Fieldless { C, } -// A C-like, fieldless enum with variants of varying name lengths. -#[derive(Debug)] -enum Fieldless0 { - A, - BBB, - CC, -} - -// A C-like, fieldless enum with 10 variants. -#[derive(Debug)] -enum Fieldless10 { - AAAAA, - BBBB, - CC, - DDDDDDDD, - E, - FFFFFFFFFFFFF, - GGGGGG, - Hatsune, - IIIIIII, - JJJJJJJJJ, -} - // An enum with multiple fieldless and fielded variants. #[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] enum Mixed { diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index d0b387dbc8b25..320c1b5861162 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -1243,49 +1243,6 @@ impl ::core::cmp::Ord for Fieldless { } } -// A C-like, fieldless enum with variants of varying name lengths. -enum Fieldless0 { A, BBB, CC, } -#[automatically_derived] -impl ::core::fmt::Debug for Fieldless0 { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::fmt::Formatter::write_str(f, - match self { - Fieldless0::A => "A", - Fieldless0::BBB => "BBB", - Fieldless0::CC => "CC", - }) - } -} - -// A C-like, fieldless enum with 10 variants. -enum Fieldless10 { - AAAAA, - BBBB, - CC, - DDDDDDDD, - E, - FFFFFFFFFFFFF, - GGGGGG, - Hatsune, - IIIIIII, - JJJJJJJJJ, -} -#[automatically_derived] -impl ::core::fmt::Debug for Fieldless10 { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - static __NAMES: &str = - "AAAAABBBBCCDDDDDDDDEFFFFFFFFFFFFFGGGGGGHatsuneIIIIIIIJJJJJJJJJ"; - static __OFFSET: [usize; 11] = - [0usize, 5usize, 9usize, 11usize, 19usize, 20usize, 33usize, - 39usize, 46usize, 53usize, 62usize]; - let __d = ::core::intrinsics::discriminant_value(self) as usize; - ::core::fmt::Formatter::debug_c_like_enum_write_str(f, __NAMES, - &__OFFSET, __d) - } -} - // An enum with multiple fieldless and fielded variants. enum Mixed { diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout index c75cc7b2179d3..689453326c0b5 100644 --- a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout @@ -15,8 +15,8 @@ macro lifetime_hygiene /* 0#0 */ { - ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 - */>) => + ($f /* 0#0 */:ident /* 0#0 */<$a /* 0#0 */:lifetime /* 0#0 */>) + => { fn /* 0#0 */ $f /* 0#0 */<$a /* 0#0 */, 'a /* 0#0 */>() {} } } fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {}