From 8c92dc84abd3756a6027238ca09a79e7b68b91fa Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 25 Feb 2026 09:20:07 -0800 Subject: [PATCH 01/77] Expand `OptionFlatten`'s iterator methods If someone considers moving from `option.into_iter().flatten()` to `option.into_flat_iter()`, it may be important for performance that this iterator "specializes" methods the same way `Flatten` does, especially forwarding to underlying `fold`, etc. --- library/core/src/option.rs | 100 +++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 3dc53941977cb..154149ffcb877 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -584,6 +584,7 @@ use crate::clone::TrivialClone; use crate::iter::{self, FusedIterator, TrustedLen}; use crate::marker::Destruct; +use crate::num::NonZero; use crate::ops::{self, ControlFlow, Deref, DerefMut, Residual, Try}; use crate::panicking::{panic, panic_display}; use crate::pin::Pin; @@ -2651,18 +2652,111 @@ impl Iterator for OptionFlatten { type Item = A::Item; fn next(&mut self) -> Option { - self.iter.as_mut()?.next() + match &mut self.iter { + Some(iter) => iter.next(), + None => None, + } } fn size_hint(&self) -> (usize, Option) { - self.iter.as_ref().map(|i| i.size_hint()).unwrap_or((0, Some(0))) + match &self.iter { + Some(iter) => iter.size_hint(), + None => (0, Some(0)), + } + } + + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + match &mut self.iter { + Some(iter) => iter.advance_by(n), + None => NonZero::new(n).map_or(Ok(()), Err), + } + } + + fn nth(&mut self, n: usize) -> Option { + match &mut self.iter { + Some(iter) => iter.nth(n), + None => None, + } + } + + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + match self.iter { + Some(iter) => iter.fold(init, fold), + None => init, + } + } + + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + match &mut self.iter { + Some(iter) => iter.try_fold(init, fold), + None => try { init }, + } + } + + fn count(self) -> usize { + match self.iter { + Some(iter) => iter.count(), + None => 0, + } + } + + fn last(self) -> Option { + match self.iter { + Some(iter) => iter.last(), + None => None, + } } } #[unstable(feature = "option_into_flat_iter", issue = "148441")] impl DoubleEndedIterator for OptionFlatten { fn next_back(&mut self) -> Option { - self.iter.as_mut()?.next_back() + match &mut self.iter { + Some(iter) => iter.next_back(), + None => None, + } + } + + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + match &mut self.iter { + Some(iter) => iter.advance_back_by(n), + None => NonZero::new(n).map_or(Ok(()), Err), + } + } + + fn nth_back(&mut self, n: usize) -> Option { + match &mut self.iter { + Some(iter) => iter.nth_back(n), + None => None, + } + } + + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + match self.iter { + Some(iter) => iter.rfold(init, fold), + None => init, + } + } + + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + match &mut self.iter { + Some(iter) => iter.try_rfold(init, fold), + None => try { init }, + } } } From c0c218589ef2be54f8776e9d761708d91914664c Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Mon, 25 May 2026 14:48:11 +0800 Subject: [PATCH 02/77] Stabilize LoongArch CRC intrinsics --- .../crates/core_arch/src/loongarch64/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/loongarch64/mod.rs b/library/stdarch/crates/core_arch/src/loongarch64/mod.rs index e8bf098a33327..bc2d941c1446c 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/mod.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/mod.rs @@ -62,56 +62,56 @@ unsafe extern "unadjusted" { /// Calculate the CRC value using the IEEE 802.3 polynomial (0xEDB88320) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crc_w_b_w(a: i8, b: i32) -> i32 { unsafe { __crc_w_b_w(a as i32, b) } } /// Calculate the CRC value using the IEEE 802.3 polynomial (0xEDB88320) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crc_w_h_w(a: i16, b: i32) -> i32 { unsafe { __crc_w_h_w(a as i32, b) } } /// Calculate the CRC value using the IEEE 802.3 polynomial (0xEDB88320) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crc_w_w_w(a: i32, b: i32) -> i32 { unsafe { __crc_w_w_w(a, b) } } /// Calculate the CRC value using the IEEE 802.3 polynomial (0xEDB88320) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crc_w_d_w(a: i64, b: i32) -> i32 { unsafe { __crc_w_d_w(a, b) } } /// Calculate the CRC value using the Castagnoli polynomial (0x82F63B78) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crcc_w_b_w(a: i8, b: i32) -> i32 { unsafe { __crcc_w_b_w(a as i32, b) } } /// Calculate the CRC value using the Castagnoli polynomial (0x82F63B78) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crcc_w_h_w(a: i16, b: i32) -> i32 { unsafe { __crcc_w_h_w(a as i32, b) } } /// Calculate the CRC value using the Castagnoli polynomial (0x82F63B78) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crcc_w_w_w(a: i32, b: i32) -> i32 { unsafe { __crcc_w_w_w(a, b) } } /// Calculate the CRC value using the Castagnoli polynomial (0x82F63B78) #[inline(always)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] +#[stable(feature = "stdarch_loongarch_crc", since = "CURRENT_RUSTC_VERSION")] pub fn crcc_w_d_w(a: i64, b: i32) -> i32 { unsafe { __crcc_w_d_w(a, b) } } From 09d22acd113e640280242e76e267689291ea3aeb Mon Sep 17 00:00:00 2001 From: sayantn Date: Sun, 31 May 2026 01:21:36 +0530 Subject: [PATCH 03/77] Correct some wrong uses of LLVM intrinsics --- .../core_arch/src/aarch64/neon/generated.rs | 2 +- .../crates/core_arch/src/aarch64/prefetch.rs | 2 +- .../core_arch/src/aarch64/sve/generated.rs | 386 ++++++++++-------- .../stdarch/crates/core_arch/src/nvptx/mod.rs | 6 +- .../crates/core_arch/src/wasm32/memory.rs | 6 +- .../stdarch/crates/core_arch/src/x86/sse.rs | 2 +- .../spec/neon/aarch64.spec.yml | 4 +- .../stdarch-gen-arm/spec/sve/aarch64.spec.yml | 59 ++- 8 files changed, 264 insertions(+), 203 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 8d701d9b88056..1b5b17e538bde 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -11903,7 +11903,7 @@ pub unsafe fn vluti4q_lane_s8(a: int8x16_t, b: uint8x8_t) -> in unsafe extern "unadjusted" { #[cfg_attr( any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.vluti4q.lane.v8i8" + link_name = "llvm.aarch64.neon.vluti4q.lane.v16i8" )] fn _vluti4q_lane_s8(a: int8x16_t, b: uint8x8_t, n: i32) -> int8x16_t; } diff --git a/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs b/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs index 4dcbc9549f115..88e5c0987f34d 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs @@ -2,7 +2,7 @@ use stdarch_test::assert_instr; unsafe extern "unadjusted" { - #[link_name = "llvm.prefetch"] + #[link_name = "llvm.prefetch.p0"] fn prefetch(p: *const i8, rw: i32, loc: i32, ty: i32); } diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs index 6c6a2476a43fd..6c5d5692a16ac 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs @@ -1843,7 +1843,7 @@ pub fn svadrd_u64base_u64index(bases: svuint64_t, indices: svuint64_t) -> svuint #[cfg_attr(test, assert_instr(and))] pub fn svand_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.and.z.nvx16i1")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.and.z.nxv16i1")] fn _svand_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t; } unsafe { _svand_b_z(pg, op1, op2) } @@ -2935,7 +2935,7 @@ pub fn svasrd_n_s64_z(pg: svbool_t, op1: svint64_t) -> svint64_ #[cfg_attr(test, assert_instr(bic))] pub fn svbic_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.bic.z.nvx16i1")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.bic.z.nxv16i1")] fn _svbic_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t; } unsafe { _svbic_b_z(pg, op1, op2) } @@ -4559,7 +4559,7 @@ pub fn svcmla_lane_f32( unsafe extern "unadjusted" { #[cfg_attr( target_arch = "aarch64", - link_name = "llvm.aarch64.sve.fcmla.lane.x.nxv4f32" + link_name = "llvm.aarch64.sve.fcmla.lane.nxv4f32" )] fn _svcmla_lane_f32( op1: svfloat32_t, @@ -7657,7 +7657,10 @@ pub fn svcvt_f64_f32_z(pg: svbool_t, op: svfloat32_t) -> svfloat64_t { #[cfg_attr(test, assert_instr(scvtf))] pub fn svcvt_f32_s32_m(inactive: svfloat32_t, pg: svbool_t, op: svint32_t) -> svfloat32_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.scvtf.f32i32")] + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.scvtf.nxv4f32.nxv4i32" + )] fn _svcvt_f32_s32_m(inactive: svfloat32_t, pg: svbool4_t, op: svint32_t) -> svfloat32_t; } unsafe { _svcvt_f32_s32_m(inactive, pg.sve_into(), op) } @@ -7681,66 +7684,137 @@ pub fn svcvt_f32_s32_z(pg: svbool_t, op: svint32_t) -> svfloat32_t { svcvt_f32_s32_m(svdup_n_f32(0.0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_s64]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u32]_m)"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(ucvtf))] +pub fn svcvt_f32_u32_m(inactive: svfloat32_t, pg: svbool_t, op: svuint32_t) -> svfloat32_t { + unsafe extern "unadjusted" { + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.ucvtf.nxv4f32.nxv4i32" + )] + fn _svcvt_f32_u32_m(inactive: svfloat32_t, pg: svbool4_t, op: svint32_t) -> svfloat32_t; + } + unsafe { _svcvt_f32_u32_m(inactive, pg.sve_into(), op.as_signed()) } +} +#[doc = "Floating-point convert"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u32]_x)"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(ucvtf))] +pub fn svcvt_f32_u32_x(pg: svbool_t, op: svuint32_t) -> svfloat32_t { + unsafe { svcvt_f32_u32_m(transmute_unchecked(op), pg, op) } +} +#[doc = "Floating-point convert"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u32]_z)"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(ucvtf))] +pub fn svcvt_f32_u32_z(pg: svbool_t, op: svuint32_t) -> svfloat32_t { + svcvt_f32_u32_m(svdup_n_f32(0.0), pg, op) +} +#[doc = "Floating-point convert"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_s64]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(scvtf))] -pub fn svcvt_f32_s64_m(inactive: svfloat32_t, pg: svbool_t, op: svint64_t) -> svfloat32_t { +pub fn svcvt_f64_s64_m(inactive: svfloat64_t, pg: svbool_t, op: svint64_t) -> svfloat64_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.scvtf.f32i64")] - fn _svcvt_f32_s64_m(inactive: svfloat32_t, pg: svbool2_t, op: svint64_t) -> svfloat32_t; + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.scvtf.nxv2f64.nxv2i64" + )] + fn _svcvt_f64_s64_m(inactive: svfloat64_t, pg: svbool2_t, op: svint64_t) -> svfloat64_t; } - unsafe { _svcvt_f32_s64_m(inactive, pg.sve_into(), op) } + unsafe { _svcvt_f64_s64_m(inactive, pg.sve_into(), op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_s64]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_s64]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(scvtf))] -pub fn svcvt_f32_s64_x(pg: svbool_t, op: svint64_t) -> svfloat32_t { - unsafe { svcvt_f32_s64_m(transmute_unchecked(op), pg, op) } +pub fn svcvt_f64_s64_x(pg: svbool_t, op: svint64_t) -> svfloat64_t { + unsafe { svcvt_f64_s64_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_s64]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_s64]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(scvtf))] -pub fn svcvt_f32_s64_z(pg: svbool_t, op: svint64_t) -> svfloat32_t { - svcvt_f32_s64_m(svdup_n_f32(0.0), pg, op) +pub fn svcvt_f64_s64_z(pg: svbool_t, op: svint64_t) -> svfloat64_t { + svcvt_f64_s64_m(svdup_n_f64(0.0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u32]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u64]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(ucvtf))] -pub fn svcvt_f32_u32_m(inactive: svfloat32_t, pg: svbool_t, op: svuint32_t) -> svfloat32_t { +pub fn svcvt_f64_u64_m(inactive: svfloat64_t, pg: svbool_t, op: svuint64_t) -> svfloat64_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.ucvtf.f32i32")] - fn _svcvt_f32_u32_m(inactive: svfloat32_t, pg: svbool4_t, op: svint32_t) -> svfloat32_t; + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.ucvtf.nxv2f64.nxv2i64" + )] + fn _svcvt_f64_u64_m(inactive: svfloat64_t, pg: svbool2_t, op: svint64_t) -> svfloat64_t; } - unsafe { _svcvt_f32_u32_m(inactive, pg.sve_into(), op.as_signed()) } + unsafe { _svcvt_f64_u64_m(inactive, pg.sve_into(), op.as_signed()) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u32]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u64]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(ucvtf))] -pub fn svcvt_f32_u32_x(pg: svbool_t, op: svuint32_t) -> svfloat32_t { - unsafe { svcvt_f32_u32_m(transmute_unchecked(op), pg, op) } +pub fn svcvt_f64_u64_x(pg: svbool_t, op: svuint64_t) -> svfloat64_t { + unsafe { svcvt_f64_u64_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u32]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u64]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(ucvtf))] -pub fn svcvt_f32_u32_z(pg: svbool_t, op: svuint32_t) -> svfloat32_t { - svcvt_f32_u32_m(svdup_n_f32(0.0), pg, op) +pub fn svcvt_f64_u64_z(pg: svbool_t, op: svuint64_t) -> svfloat64_t { + svcvt_f64_u64_m(svdup_n_f64(0.0), pg, op) +} +#[doc = "Floating-point convert"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_s64]_m)"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(scvtf))] +pub fn svcvt_f32_s64_m(inactive: svfloat32_t, pg: svbool_t, op: svint64_t) -> svfloat32_t { + unsafe extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.scvtf.f32i64")] + fn _svcvt_f32_s64_m(inactive: svfloat32_t, pg: svbool2_t, op: svint64_t) -> svfloat32_t; + } + unsafe { _svcvt_f32_s64_m(inactive, pg.sve_into(), op) } +} +#[doc = "Floating-point convert"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_s64]_x)"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(scvtf))] +pub fn svcvt_f32_s64_x(pg: svbool_t, op: svint64_t) -> svfloat32_t { + unsafe { svcvt_f32_s64_m(transmute_unchecked(op), pg, op) } +} +#[doc = "Floating-point convert"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_s64]_z)"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(scvtf))] +pub fn svcvt_f32_s64_z(pg: svbool_t, op: svint64_t) -> svfloat32_t { + svcvt_f32_s64_m(svdup_n_f32(0.0), pg, op) } #[doc = "Floating-point convert"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f32[_u64]_m)"] @@ -7805,37 +7879,6 @@ pub fn svcvt_f64_s32_z(pg: svbool_t, op: svint32_t) -> svfloat64_t { svcvt_f64_s32_m(svdup_n_f64(0.0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_s64]_m)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(scvtf))] -pub fn svcvt_f64_s64_m(inactive: svfloat64_t, pg: svbool_t, op: svint64_t) -> svfloat64_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.scvtf.f64i64")] - fn _svcvt_f64_s64_m(inactive: svfloat64_t, pg: svbool2_t, op: svint64_t) -> svfloat64_t; - } - unsafe { _svcvt_f64_s64_m(inactive, pg.sve_into(), op) } -} -#[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_s64]_x)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(scvtf))] -pub fn svcvt_f64_s64_x(pg: svbool_t, op: svint64_t) -> svfloat64_t { - unsafe { svcvt_f64_s64_m(transmute_unchecked(op), pg, op) } -} -#[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_s64]_z)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(scvtf))] -pub fn svcvt_f64_s64_z(pg: svbool_t, op: svint64_t) -> svfloat64_t { - svcvt_f64_s64_m(svdup_n_f64(0.0), pg, op) -} -#[doc = "Floating-point convert"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u32]_m)"] #[inline] #[target_feature(enable = "sve")] @@ -7867,190 +7910,202 @@ pub fn svcvt_f64_u32_z(pg: svbool_t, op: svuint32_t) -> svfloat64_t { svcvt_f64_u32_m(svdup_n_f64(0.0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u64]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f32]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(ucvtf))] -pub fn svcvt_f64_u64_m(inactive: svfloat64_t, pg: svbool_t, op: svuint64_t) -> svfloat64_t { +#[cfg_attr(test, assert_instr(fcvtzs))] +pub fn svcvt_s32_f32_m(inactive: svint32_t, pg: svbool_t, op: svfloat32_t) -> svint32_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.ucvtf.f64i64")] - fn _svcvt_f64_u64_m(inactive: svfloat64_t, pg: svbool2_t, op: svint64_t) -> svfloat64_t; + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.fcvtzs.nxv4i32.nxv4f32" + )] + fn _svcvt_s32_f32_m(inactive: svint32_t, pg: svbool4_t, op: svfloat32_t) -> svint32_t; } - unsafe { _svcvt_f64_u64_m(inactive, pg.sve_into(), op.as_signed()) } + unsafe { _svcvt_s32_f32_m(inactive, pg.sve_into(), op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u64]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f32]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(ucvtf))] -pub fn svcvt_f64_u64_x(pg: svbool_t, op: svuint64_t) -> svfloat64_t { - unsafe { svcvt_f64_u64_m(transmute_unchecked(op), pg, op) } +#[cfg_attr(test, assert_instr(fcvtzs))] +pub fn svcvt_s32_f32_x(pg: svbool_t, op: svfloat32_t) -> svint32_t { + unsafe { svcvt_s32_f32_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_f64[_u64]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f32]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(ucvtf))] -pub fn svcvt_f64_u64_z(pg: svbool_t, op: svuint64_t) -> svfloat64_t { - svcvt_f64_u64_m(svdup_n_f64(0.0), pg, op) +#[cfg_attr(test, assert_instr(fcvtzs))] +pub fn svcvt_s32_f32_z(pg: svbool_t, op: svfloat32_t) -> svint32_t { + svcvt_s32_f32_m(svdup_n_s32(0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f32]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f64]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s32_f32_m(inactive: svint32_t, pg: svbool_t, op: svfloat32_t) -> svint32_t { +pub fn svcvt_s64_f64_m(inactive: svint64_t, pg: svbool_t, op: svfloat64_t) -> svint64_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzs.i32f32")] - fn _svcvt_s32_f32_m(inactive: svint32_t, pg: svbool4_t, op: svfloat32_t) -> svint32_t; + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.fcvtzs.nxv2i64.nxv2f64" + )] + fn _svcvt_s64_f64_m(inactive: svint64_t, pg: svbool2_t, op: svfloat64_t) -> svint64_t; } - unsafe { _svcvt_s32_f32_m(inactive, pg.sve_into(), op) } + unsafe { _svcvt_s64_f64_m(inactive, pg.sve_into(), op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f32]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f64]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s32_f32_x(pg: svbool_t, op: svfloat32_t) -> svint32_t { - unsafe { svcvt_s32_f32_m(transmute_unchecked(op), pg, op) } +pub fn svcvt_s64_f64_x(pg: svbool_t, op: svfloat64_t) -> svint64_t { + unsafe { svcvt_s64_f64_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f32]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f64]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s32_f32_z(pg: svbool_t, op: svfloat32_t) -> svint32_t { - svcvt_s32_f32_m(svdup_n_s32(0), pg, op) +pub fn svcvt_s64_f64_z(pg: svbool_t, op: svfloat64_t) -> svint64_t { + svcvt_s64_f64_m(svdup_n_s64(0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f64]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f32]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s32_f64_m(inactive: svint32_t, pg: svbool_t, op: svfloat64_t) -> svint32_t { +#[cfg_attr(test, assert_instr(fcvtzu))] +pub fn svcvt_u32_f32_m(inactive: svuint32_t, pg: svbool_t, op: svfloat32_t) -> svuint32_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzs.i32f64")] - fn _svcvt_s32_f64_m(inactive: svint32_t, pg: svbool2_t, op: svfloat64_t) -> svint32_t; + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.fcvtzu.nxv4i32.nxv4f32" + )] + fn _svcvt_u32_f32_m(inactive: svint32_t, pg: svbool4_t, op: svfloat32_t) -> svint32_t; } - unsafe { _svcvt_s32_f64_m(inactive, pg.sve_into(), op) } + unsafe { _svcvt_u32_f32_m(inactive.as_signed(), pg.sve_into(), op).as_unsigned() } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f64]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f32]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s32_f64_x(pg: svbool_t, op: svfloat64_t) -> svint32_t { - unsafe { svcvt_s32_f64_m(transmute_unchecked(op), pg, op) } +#[cfg_attr(test, assert_instr(fcvtzu))] +pub fn svcvt_u32_f32_x(pg: svbool_t, op: svfloat32_t) -> svuint32_t { + unsafe { svcvt_u32_f32_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f64]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f32]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s32_f64_z(pg: svbool_t, op: svfloat64_t) -> svint32_t { - svcvt_s32_f64_m(svdup_n_s32(0), pg, op) +#[cfg_attr(test, assert_instr(fcvtzu))] +pub fn svcvt_u32_f32_z(pg: svbool_t, op: svfloat32_t) -> svuint32_t { + svcvt_u32_f32_m(svdup_n_u32(0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f32]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u64[_f64]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s64_f32_m(inactive: svint64_t, pg: svbool_t, op: svfloat32_t) -> svint64_t { +#[cfg_attr(test, assert_instr(fcvtzu))] +pub fn svcvt_u64_f64_m(inactive: svuint64_t, pg: svbool_t, op: svfloat64_t) -> svuint64_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzs.i64f32")] - fn _svcvt_s64_f32_m(inactive: svint64_t, pg: svbool2_t, op: svfloat32_t) -> svint64_t; + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.fcvtzu.nxv2i64.nxv2f64" + )] + fn _svcvt_u64_f64_m(inactive: svint64_t, pg: svbool2_t, op: svfloat64_t) -> svint64_t; } - unsafe { _svcvt_s64_f32_m(inactive, pg.sve_into(), op) } + unsafe { _svcvt_u64_f64_m(inactive.as_signed(), pg.sve_into(), op).as_unsigned() } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f32]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u64[_f64]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s64_f32_x(pg: svbool_t, op: svfloat32_t) -> svint64_t { - unsafe { svcvt_s64_f32_m(transmute_unchecked(op), pg, op) } +#[cfg_attr(test, assert_instr(fcvtzu))] +pub fn svcvt_u64_f64_x(pg: svbool_t, op: svfloat64_t) -> svuint64_t { + unsafe { svcvt_u64_f64_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f32]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u64[_f64]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s64_f32_z(pg: svbool_t, op: svfloat32_t) -> svint64_t { - svcvt_s64_f32_m(svdup_n_s64(0), pg, op) +#[cfg_attr(test, assert_instr(fcvtzu))] +pub fn svcvt_u64_f64_z(pg: svbool_t, op: svfloat64_t) -> svuint64_t { + svcvt_u64_f64_m(svdup_n_u64(0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f64]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f64]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s64_f64_m(inactive: svint64_t, pg: svbool_t, op: svfloat64_t) -> svint64_t { +pub fn svcvt_s32_f64_m(inactive: svint32_t, pg: svbool_t, op: svfloat64_t) -> svint32_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzs.i64f64")] - fn _svcvt_s64_f64_m(inactive: svint64_t, pg: svbool2_t, op: svfloat64_t) -> svint64_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzs.i32f64")] + fn _svcvt_s32_f64_m(inactive: svint32_t, pg: svbool2_t, op: svfloat64_t) -> svint32_t; } - unsafe { _svcvt_s64_f64_m(inactive, pg.sve_into(), op) } + unsafe { _svcvt_s32_f64_m(inactive, pg.sve_into(), op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f64]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f64]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s64_f64_x(pg: svbool_t, op: svfloat64_t) -> svint64_t { - unsafe { svcvt_s64_f64_m(transmute_unchecked(op), pg, op) } +pub fn svcvt_s32_f64_x(pg: svbool_t, op: svfloat64_t) -> svint32_t { + unsafe { svcvt_s32_f64_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f64]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s32[_f64]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] #[cfg_attr(test, assert_instr(fcvtzs))] -pub fn svcvt_s64_f64_z(pg: svbool_t, op: svfloat64_t) -> svint64_t { - svcvt_s64_f64_m(svdup_n_s64(0), pg, op) +pub fn svcvt_s32_f64_z(pg: svbool_t, op: svfloat64_t) -> svint32_t { + svcvt_s32_f64_m(svdup_n_s32(0), pg, op) } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f32]_m)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f32]_m)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzu))] -pub fn svcvt_u32_f32_m(inactive: svuint32_t, pg: svbool_t, op: svfloat32_t) -> svuint32_t { +#[cfg_attr(test, assert_instr(fcvtzs))] +pub fn svcvt_s64_f32_m(inactive: svint64_t, pg: svbool_t, op: svfloat32_t) -> svint64_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzu.i32f32")] - fn _svcvt_u32_f32_m(inactive: svint32_t, pg: svbool4_t, op: svfloat32_t) -> svint32_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzs.i64f32")] + fn _svcvt_s64_f32_m(inactive: svint64_t, pg: svbool2_t, op: svfloat32_t) -> svint64_t; } - unsafe { _svcvt_u32_f32_m(inactive.as_signed(), pg.sve_into(), op).as_unsigned() } + unsafe { _svcvt_s64_f32_m(inactive, pg.sve_into(), op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f32]_x)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f32]_x)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzu))] -pub fn svcvt_u32_f32_x(pg: svbool_t, op: svfloat32_t) -> svuint32_t { - unsafe { svcvt_u32_f32_m(transmute_unchecked(op), pg, op) } +#[cfg_attr(test, assert_instr(fcvtzs))] +pub fn svcvt_s64_f32_x(pg: svbool_t, op: svfloat32_t) -> svint64_t { + unsafe { svcvt_s64_f32_m(transmute_unchecked(op), pg, op) } } #[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f32]_z)"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_s64[_f32]_z)"] #[inline] #[target_feature(enable = "sve")] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzu))] -pub fn svcvt_u32_f32_z(pg: svbool_t, op: svfloat32_t) -> svuint32_t { - svcvt_u32_f32_m(svdup_n_u32(0), pg, op) +#[cfg_attr(test, assert_instr(fcvtzs))] +pub fn svcvt_s64_f32_z(pg: svbool_t, op: svfloat32_t) -> svint64_t { + svcvt_s64_f32_m(svdup_n_s64(0), pg, op) } #[doc = "Floating-point convert"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u32[_f64]_m)"] @@ -8114,37 +8169,6 @@ pub fn svcvt_u64_f32_x(pg: svbool_t, op: svfloat32_t) -> svuint64_t { pub fn svcvt_u64_f32_z(pg: svbool_t, op: svfloat32_t) -> svuint64_t { svcvt_u64_f32_m(svdup_n_u64(0), pg, op) } -#[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u64[_f64]_m)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzu))] -pub fn svcvt_u64_f64_m(inactive: svuint64_t, pg: svbool_t, op: svfloat64_t) -> svuint64_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fcvtzu.i64f64")] - fn _svcvt_u64_f64_m(inactive: svint64_t, pg: svbool2_t, op: svfloat64_t) -> svint64_t; - } - unsafe { _svcvt_u64_f64_m(inactive.as_signed(), pg.sve_into(), op).as_unsigned() } -} -#[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u64[_f64]_x)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzu))] -pub fn svcvt_u64_f64_x(pg: svbool_t, op: svfloat64_t) -> svuint64_t { - unsafe { svcvt_u64_f64_m(transmute_unchecked(op), pg, op) } -} -#[doc = "Floating-point convert"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svcvt_u64[_f64]_z)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(fcvtzu))] -pub fn svcvt_u64_f64_z(pg: svbool_t, op: svfloat64_t) -> svuint64_t { - svcvt_u64_f64_m(svdup_n_u64(0), pg, op) -} #[doc = "Divide"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svdiv[_f32]_m)"] #[inline] @@ -10040,7 +10064,7 @@ pub fn svdupq_n_u8( #[cfg_attr(test, assert_instr(eor))] pub fn sveor_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.eor.z.nvx16i1")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.eor.z.nxv16i1")] fn _sveor_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t; } unsafe { _sveor_b_z(pg, op1, op2) } @@ -10591,7 +10615,7 @@ pub fn svexpa_f32(op: svuint32_t) -> svfloat32_t { unsafe extern "unadjusted" { #[cfg_attr( target_arch = "aarch64", - link_name = "llvm.aarch64.sve.fexpa.x.nxv4f32 " + link_name = "llvm.aarch64.sve.fexpa.x.nxv4f32" )] fn _svexpa_f32(op: svint32_t) -> svfloat32_t; } @@ -10607,7 +10631,7 @@ pub fn svexpa_f64(op: svuint64_t) -> svfloat64_t { unsafe extern "unadjusted" { #[cfg_attr( target_arch = "aarch64", - link_name = "llvm.aarch64.sve.fexpa.x.nxv2f64 " + link_name = "llvm.aarch64.sve.fexpa.x.nxv2f64" )] fn _svexpa_f64(op: svint64_t) -> svfloat64_t; } @@ -27371,7 +27395,10 @@ pub fn svmls_lane_f64( #[cfg_attr(test, assert_instr(fmmla))] pub fn svmmla_f32(op1: svfloat32_t, op2: svfloat32_t, op3: svfloat32_t) -> svfloat32_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fmmla.nxv4f32")] + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.fmmla.nxv4f32.nxv4f32" + )] fn _svmmla_f32(op1: svfloat32_t, op2: svfloat32_t, op3: svfloat32_t) -> svfloat32_t; } unsafe { _svmmla_f32(op1, op2, op3) } @@ -27384,7 +27411,10 @@ pub fn svmmla_f32(op1: svfloat32_t, op2: svfloat32_t, op3: svfloat32_t) -> svflo #[cfg_attr(test, assert_instr(fmmla))] pub fn svmmla_f64(op1: svfloat64_t, op2: svfloat64_t, op3: svfloat64_t) -> svfloat64_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.fmmla.nxv2f64")] + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.fmmla.nxv2f64.nxv2f64" + )] fn _svmmla_f64(op1: svfloat64_t, op2: svfloat64_t, op3: svfloat64_t) -> svfloat64_t; } unsafe { _svmmla_f64(op1, op2, op3) } @@ -30260,7 +30290,7 @@ pub fn svnot_u64_z(pg: svbool_t, op: svuint64_t) -> svuint64_t { #[cfg_attr(test, assert_instr(orn))] pub fn svorn_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.orn.z.nvx16i1")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.orn.z.nxv16i1")] fn _svorn_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t; } unsafe { _svorn_b_z(pg, op1, op2) } @@ -30273,7 +30303,7 @@ pub fn svorn_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(orr))] pub fn svorr_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.orr.z.nvx16i1")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.orr.z.nxv16i1")] fn _svorr_b_z(pg: svbool_t, op1: svbool_t, op2: svbool_t) -> svbool_t; } unsafe { _svorr_b_z(pg, op1, op2) } @@ -34340,10 +34370,7 @@ pub fn svrecps_f64(op1: svfloat64_t, op2: svfloat64_t) -> svfloat64_t { #[cfg_attr(test, assert_instr(frecpx))] pub fn svrecpx_f32_m(inactive: svfloat32_t, pg: svbool_t, op: svfloat32_t) -> svfloat32_t { unsafe extern "unadjusted" { - #[cfg_attr( - target_arch = "aarch64", - link_name = "llvm.aarch64.sve.frecpx.x.nxv4f32" - )] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.frecpx.nxv4f32")] fn _svrecpx_f32_m(inactive: svfloat32_t, pg: svbool4_t, op: svfloat32_t) -> svfloat32_t; } unsafe { _svrecpx_f32_m(inactive, pg.sve_into(), op) } @@ -34374,10 +34401,7 @@ pub fn svrecpx_f32_z(pg: svbool_t, op: svfloat32_t) -> svfloat32_t { #[cfg_attr(test, assert_instr(frecpx))] pub fn svrecpx_f64_m(inactive: svfloat64_t, pg: svbool_t, op: svfloat64_t) -> svfloat64_t { unsafe extern "unadjusted" { - #[cfg_attr( - target_arch = "aarch64", - link_name = "llvm.aarch64.sve.frecpx.x.nxv2f64" - )] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.frecpx.nxv2f64")] fn _svrecpx_f64_m(inactive: svfloat64_t, pg: svbool2_t, op: svfloat64_t) -> svfloat64_t; } unsafe { _svrecpx_f64_m(inactive, pg.sve_into(), op) } diff --git a/library/stdarch/crates/core_arch/src/nvptx/mod.rs b/library/stdarch/crates/core_arch/src/nvptx/mod.rs index b63a5d01a7a22..84d8810320a15 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/mod.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/mod.rs @@ -20,8 +20,8 @@ pub use packed::*; #[allow(improper_ctypes)] unsafe extern "C" { - #[link_name = "llvm.nvvm.barrier0"] - fn syncthreads() -> (); + #[link_name = "llvm.nvvm.barrier.cta.sync.aligned.all"] + fn syncthreads(a: u32) -> (); #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.x"] fn block_dim_x() -> u32; #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.y"] @@ -54,7 +54,7 @@ unsafe extern "C" { #[inline] #[unstable(feature = "stdarch_nvptx", issue = "111199")] pub unsafe fn _syncthreads() -> () { - syncthreads() + syncthreads(0) } /// x-th thread-block dimension. diff --git a/library/stdarch/crates/core_arch/src/wasm32/memory.rs b/library/stdarch/crates/core_arch/src/wasm32/memory.rs index 90e9075e5136b..9d7b7287ede1b 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/memory.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/memory.rs @@ -2,9 +2,11 @@ use stdarch_test::assert_instr; unsafe extern "unadjusted" { - #[link_name = "llvm.wasm.memory.grow"] + #[cfg_attr(target_pointer_width = "32", link_name = "llvm.wasm.memory.grow.i32")] + #[cfg_attr(target_pointer_width = "64", link_name = "llvm.wasm.memory.grow.i64")] fn llvm_memory_grow(mem: u32, pages: usize) -> usize; - #[link_name = "llvm.wasm.memory.size"] + #[cfg_attr(target_pointer_width = "32", link_name = "llvm.wasm.memory.size.i32")] + #[cfg_attr(target_pointer_width = "64", link_name = "llvm.wasm.memory.size.i64")] fn llvm_memory_size(mem: u32) -> usize; } diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index 867387290119b..afaaccfbf27f4 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -2040,7 +2040,7 @@ unsafe extern "C" { fn stmxcsr(p: *mut i8); #[link_name = "llvm.x86.sse.ldmxcsr"] fn ldmxcsr(p: *const i8); - #[link_name = "llvm.prefetch"] + #[link_name = "llvm.prefetch.p0"] fn prefetch(p: *const i8, rw: i32, loc: i32, ty: i32); #[link_name = "llvm.x86.sse.cmp.ss"] fn cmpss(a: __m128, b: __m128, imm8: i8) -> __m128; diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index 03fea5e0a4af3..e5ce77ed8b33f 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -13951,7 +13951,7 @@ intrinsics: - 'b: {neon_type[1]}' - 'n: i32' links: - - link: "llvm.aarch64.neon.vluti4q.lane.{neon_type[1]}" + - link: "llvm.aarch64.neon.vluti4q.lane.{neon_type[0]}" arch: aarch64,arm64ec - FnCall: ['_vluti4{neon_type[0].lane_nox}', [a, b, LANE]] @@ -14002,7 +14002,7 @@ intrinsics: - 'b: {neon_type[1]}' - 'n: i32' links: - - link: "llvm.aarch64.neon.vluti4q.laneq.{neon_type[1]}" + - link: "llvm.aarch64.neon.vluti4q.laneq.{neon_type[0]}" arch: aarch64,arm64ec - FnCall: ['_vluti4{neon_type[0].laneq_nox}', [a, b, LANE]] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml index 29dd3a095d7e6..1f65732412241 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml @@ -115,7 +115,7 @@ intrinsics: assert_instr: [[fcmla, "IMM_INDEX = 0, IMM_ROTATION = 90"]] compose: - LLVMLink: - name: fcmla.lane.x.{sve_type} + name: fcmla.lane.{sve_type} arguments: - "op1: {sve_type}" - "op2: {sve_type}" @@ -4179,7 +4179,8 @@ intrinsics: ["inactive: {sve_type[0]}", "pg: {max_predicate}", "op: {sve_type[1]}"] return_type: "{sve_type[0]}" types: - - [[f32, f64], [i32, u32, i64, u64]] + - [f32, [i64, u64]] + - [f64, [i32, u32]] zeroing_method: { drop: inactive } substitutions: convert_from: { match_kind: "{type[1]}", default: s, unsigned: u } @@ -4187,6 +4188,23 @@ intrinsics: compose: - LLVMLink: name: "{convert_from}cvtf.{type[0]}{type[1]}" + + - name: svcvt_{type[0]}[_{type[1]}]{_mxz} + attr: [*sve-unstable] + doc: Floating-point convert + arguments: + ["inactive: {sve_type[0]}", "pg: {max_predicate}", "op: {sve_type[1]}"] + return_type: "{sve_type[0]}" + types: + - [f32, [i32, u32]] + - [f64, [i64, u64]] + zeroing_method: { drop: inactive } + substitutions: + convert_from: { match_kind: "{type[1]}", default: s, unsigned: u } + assert_instr: ["{convert_from}cvtf"] + compose: + - LLVMLink: + name: "{convert_from}cvtf.{sve_type[0]}.{sve_type[1]}" - name: svcvt_{type[0]}[_{type[1]}]{_mxz} attr: [*sve-unstable] @@ -4195,13 +4213,30 @@ intrinsics: ["inactive: {sve_type[0]}", "pg: {max_predicate}", "op: {sve_type[1]}"] return_type: "{sve_type[0]}" types: - - [[i32, u32, i64, u64], [f32, f64]] + - [[i32, u32], f64] + - [[i64, u64], f32] zeroing_method: { drop: inactive } substitutions: convert_to: { match_kind: "{type[0]}", default: s, unsigned: u } assert_instr: ["fcvtz{convert_to}"] compose: - LLVMLink: { name: "fcvtz{convert_to}.{type[0]}{type[1]}" } + + - name: svcvt_{type[0]}[_{type[1]}]{_mxz} + attr: [*sve-unstable] + doc: Floating-point convert + arguments: + ["inactive: {sve_type[0]}", "pg: {max_predicate}", "op: {sve_type[1]}"] + return_type: "{sve_type[0]}" + types: + - [[i32, u32], f32] + - [[i64, u64], f64] + zeroing_method: { drop: inactive } + substitutions: + convert_to: { match_kind: "{type[0]}", default: s, unsigned: u } + assert_instr: ["fcvtz{convert_to}"] + compose: + - LLVMLink: { name: "fcvtz{convert_to}.{sve_type[0]}.{sve_type[1]}" } - name: svcvt_{type[0]}[_{type[1]}]{_mxz} attr: [*sve-unstable] @@ -4356,7 +4391,7 @@ intrinsics: return_type: svbool_t assert_instr: [and] compose: - - LLVMLink: { name: "and.z.nvx16i1" } + - LLVMLink: { name: "and.z.nxv16i1" } - name: svmov[_b]_z attr: [*sve-unstable] @@ -4386,7 +4421,7 @@ intrinsics: return_type: svbool_t assert_instr: [bic] compose: - - LLVMLink: { name: "bic.z.nvx16i1" } + - LLVMLink: { name: "bic.z.nxv16i1" } - name: sveor[{_n}_{type}]{_mxz} attr: [*sve-unstable] @@ -4417,7 +4452,7 @@ intrinsics: return_type: svbool_t assert_instr: [eor] compose: - - LLVMLink: { name: "eor.z.nvx16i1" } + - LLVMLink: { name: "eor.z.nxv16i1" } - name: svnot[_{type}]{_mxz} attr: [*sve-unstable] @@ -4497,7 +4532,7 @@ intrinsics: return_type: svbool_t assert_instr: [orr] compose: - - LLVMLink: { name: "orr.z.nvx16i1" } + - LLVMLink: { name: "orr.z.nxv16i1" } - name: svorn[_b]_z attr: [*sve-unstable] @@ -4506,7 +4541,7 @@ intrinsics: return_type: svbool_t assert_instr: [orn] compose: - - LLVMLink: { name: "orn.z.nvx16i1" } + - LLVMLink: { name: "orn.z.nxv16i1" } - name: svlsl[{_n}_{type[0]}]{_mxz} attr: [*sve-unstable] @@ -4749,7 +4784,7 @@ intrinsics: assert_instr: [frecpx] zeroing_method: { drop: inactive } compose: - - LLVMLink: { name: "frecpx.x.{sve_type}" } + - LLVMLink: { name: "frecpx.{sve_type}" } - name: svrsqrte[_{type}] attr: [*sve-unstable] @@ -5115,7 +5150,7 @@ intrinsics: types: [[f32, u32], [f64, u64]] assert_instr: [fexpa] compose: - - LLVMLink: { name: "fexpa.x.{sve_type[0]} " } + - LLVMLink: { name: "fexpa.x.{sve_type[0]}" } - name: svscale[{_n}_{type[0]}]{_mxz} attr: [*sve-unstable] @@ -5139,7 +5174,7 @@ intrinsics: types: [f32] assert_instr: [fmmla] compose: - - LLVMLink: { name: "fmmla.{sve_type}" } + - LLVMLink: { name: "fmmla.{sve_type}.{sve_type}" } - name: svmmla[_{type}] attr: [*sve-unstable] @@ -5150,7 +5185,7 @@ intrinsics: types: [f64] assert_instr: [fmmla] compose: - - LLVMLink: { name: "fmmla.{sve_type}" } + - LLVMLink: { name: "fmmla.{sve_type}.{sve_type}" } - name: svmmla[_{type[0]}] attr: [*sve-unstable] From 2dd54ff3227d07f6e975e9cbfe3b39a76abebfd2 Mon Sep 17 00:00:00 2001 From: sayantn Date: Sun, 31 May 2026 12:36:47 +0530 Subject: [PATCH 04/77] Use `unadjusted` ABI everywhere --- library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs | 4 ++-- library/stdarch/crates/core_arch/src/mips/msa.rs | 2 +- library/stdarch/crates/core_arch/src/nvptx/mod.rs | 2 +- library/stdarch/crates/core_arch/src/nvptx/packed.rs | 2 +- library/stdarch/crates/core_arch/src/powerpc/altivec.rs | 2 +- library/stdarch/crates/core_arch/src/powerpc/vsx.rs | 2 +- library/stdarch/crates/core_arch/src/powerpc64/vsx.rs | 2 +- library/stdarch/crates/core_arch/src/x86/aes.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx2.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512bf16.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512bw.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512cd.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512dq.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512f.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512ifma.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avx512vnni.rs | 2 +- .../stdarch/crates/core_arch/src/x86/avx512vp2intersect.rs | 2 +- library/stdarch/crates/core_arch/src/x86/avxneconvert.rs | 2 +- library/stdarch/crates/core_arch/src/x86/bmi1.rs | 2 +- library/stdarch/crates/core_arch/src/x86/bmi2.rs | 2 +- library/stdarch/crates/core_arch/src/x86/fxsr.rs | 2 +- library/stdarch/crates/core_arch/src/x86/gfni.rs | 2 +- library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs | 2 +- library/stdarch/crates/core_arch/src/x86/rtm.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sha.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sse.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sse2.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sse3.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sse41.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sse42.rs | 2 +- library/stdarch/crates/core_arch/src/x86/sse4a.rs | 2 +- library/stdarch/crates/core_arch/src/x86/ssse3.rs | 2 +- library/stdarch/crates/core_arch/src/x86/tbm.rs | 2 +- library/stdarch/crates/core_arch/src/x86/vaes.rs | 2 +- library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs | 2 +- library/stdarch/crates/core_arch/src/x86/xsave.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/amx.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/avx512f.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/bmi.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/bmi2.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/fxsr.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/sse.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/sse2.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/sse42.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/tbm.rs | 2 +- library/stdarch/crates/core_arch/src/x86_64/xsave.rs | 2 +- 51 files changed, 52 insertions(+), 52 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs index a3f70ab61c40f..c6d5d57aca869 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs @@ -130,7 +130,7 @@ macro_rules! impl_internal_sve_predicate { #[target_feature(enable = "sve")] unsafe fn sve_into(self) -> svbool_t { #[allow(improper_ctypes)] - unsafe extern "C" { + unsafe extern "unadjusted" { #[cfg_attr( target_arch = "aarch64", link_name = concat!("llvm.aarch64.sve.convert.to.svbool.nxv", $elt, "i1") @@ -147,7 +147,7 @@ macro_rules! impl_internal_sve_predicate { #[target_feature(enable = "sve")] unsafe fn sve_into(self) -> $name { #[allow(improper_ctypes)] - unsafe extern "C" { + unsafe extern "unadjusted" { #[cfg_attr( target_arch = "aarch64", link_name = concat!("llvm.aarch64.sve.convert.from.svbool.nxv", $elt, "i1") diff --git a/library/stdarch/crates/core_arch/src/mips/msa.rs b/library/stdarch/crates/core_arch/src/mips/msa.rs index bc601baef9e2a..dab64319ccc3b 100644 --- a/library/stdarch/crates/core_arch/src/mips/msa.rs +++ b/library/stdarch/crates/core_arch/src/mips/msa.rs @@ -45,7 +45,7 @@ types! { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.mips.add.a.b"] fn msa_add_a_b(a: v16i8, b: v16i8) -> v16i8; #[link_name = "llvm.mips.add.a.h"] diff --git a/library/stdarch/crates/core_arch/src/nvptx/mod.rs b/library/stdarch/crates/core_arch/src/nvptx/mod.rs index 84d8810320a15..d22f3a25bf70e 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/mod.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/mod.rs @@ -19,7 +19,7 @@ mod packed; pub use packed::*; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.nvvm.barrier.cta.sync.aligned.all"] fn syncthreads(a: u32) -> (); #[link_name = "llvm.nvvm.read.ptx.sreg.ntid.x"] diff --git a/library/stdarch/crates/core_arch/src/nvptx/packed.rs b/library/stdarch/crates/core_arch/src/nvptx/packed.rs index 1c7e81268fc99..7e6c14bc993d9 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/packed.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/packed.rs @@ -7,7 +7,7 @@ use crate::intrinsics::simd::*; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.minimum.v2f16"] fn llvm_f16x2_minimum(a: f16x2, b: f16x2) -> f16x2; #[link_name = "llvm.maximum.v2f16"] diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index 78ec39f91ff33..ccfed88a93c2a 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -96,7 +96,7 @@ impl From for m32x4 { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.ppc.altivec.lvx"] fn lvx(p: *const i8) -> vector_unsigned_int; diff --git a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs index 4a7b561a20c55..60cb2ad44cd4e 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs @@ -52,7 +52,7 @@ impl From for m64x2 { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.ppc.altivec.vperm"] fn vperm( a: vector_signed_int, diff --git a/library/stdarch/crates/core_arch/src/powerpc64/vsx.rs b/library/stdarch/crates/core_arch/src/powerpc64/vsx.rs index 7b42be8653c55..9032e7795980f 100644 --- a/library/stdarch/crates/core_arch/src/powerpc64/vsx.rs +++ b/library/stdarch/crates/core_arch/src/powerpc64/vsx.rs @@ -17,7 +17,7 @@ use stdarch_test::assert_instr; use crate::mem::transmute; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.ppc.vsx.lxvl"] fn lxvl(a: *const u8, l: usize) -> vector_signed_int; diff --git a/library/stdarch/crates/core_arch/src/x86/aes.rs b/library/stdarch/crates/core_arch/src/x86/aes.rs index d07ab4dc2a01e..ecb09a6a9099f 100644 --- a/library/stdarch/crates/core_arch/src/x86/aes.rs +++ b/library/stdarch/crates/core_arch/src/x86/aes.rs @@ -13,7 +13,7 @@ use crate::core_arch::x86::__m128i; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.aesni.aesdec"] fn aesdec(a: __m128i, round_key: __m128i) -> __m128i; #[link_name = "llvm.x86.aesni.aesdeclast"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index ef434205b52a0..f5ddff6457aea 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -3292,7 +3292,7 @@ pub const fn _mm256_cvtss_f32(a: __m256) -> f32 { // LLVM intrinsics used in the above functions #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx.round.pd.256"] fn roundpd256(a: __m256d, b: i32) -> __m256d; #[link_name = "llvm.x86.avx.round.ps.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index b49ad9522a412..6925ba8e27028 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -3906,7 +3906,7 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx2.pmadd.wd"] fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs b/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs index 8d944f5ba817b..230a4f3754cad 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs @@ -9,7 +9,7 @@ use crate::intrinsics::simd::*; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512bf16.cvtne2ps2bf16.128"] fn cvtne2ps2bf16(a: f32x4, b: f32x4) -> i16x8; #[link_name = "llvm.x86.avx512bf16.cvtne2ps2bf16.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs b/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs index dd211854afbb4..344130fb6e720 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs @@ -27,7 +27,7 @@ use crate::mem::transmute; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.vpshufbitqmb.512"] fn bitshuffle_512(data: i8x64, indices: i8x64) -> __mmask64; #[link_name = "llvm.x86.avx512.vpshufbitqmb.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 659d6c3be88e7..50d57b4964489 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -12764,7 +12764,7 @@ pub unsafe fn _mm_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.pmul.hr.sw.512"] fn vpmulhrsw(a: i16x32, b: i16x32) -> i16x32; diff --git a/library/stdarch/crates/core_arch/src/x86/avx512cd.rs b/library/stdarch/crates/core_arch/src/x86/avx512cd.rs index 4082433e70759..378bc3617ed63 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512cd.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512cd.rs @@ -563,7 +563,7 @@ pub const fn _mm_maskz_lzcnt_epi64(k: __mmask8, a: __m128i) -> __m128i { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.conflict.d.512"] fn vpconflictd(a: i32x16) -> i32x16; #[link_name = "llvm.x86.avx512.conflict.d.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512dq.rs b/library/stdarch/crates/core_arch/src/x86/avx512dq.rs index 0b322c8b83c7b..5fe40b7541549 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512dq.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512dq.rs @@ -7235,7 +7235,7 @@ pub fn _mm_mask_fpclass_ss_mask(k1: __mmask8, a: __m128) -> __m } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.sitofp.round.v2f64.v2i64"] fn vcvtqq2pd_128(a: i64x2, rounding: i32) -> f64x2; #[link_name = "llvm.x86.avx512.sitofp.round.v4f64.v4i64"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 66ea63b674f12..225e447cea441 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -44215,7 +44215,7 @@ pub const _MM_PERM_DDDC: _MM_PERM_ENUM = 0xFE; pub const _MM_PERM_DDDD: _MM_PERM_ENUM = 0xFF; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.sqrt.ps.512"] fn vsqrtps(a: f32x16, rounding: i32) -> f32x16; #[link_name = "llvm.x86.avx512.sqrt.pd.512"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512ifma.rs b/library/stdarch/crates/core_arch/src/x86/avx512ifma.rs index 5ce28565d1085..262215e62c43d 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512ifma.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512ifma.rs @@ -347,7 +347,7 @@ pub fn _mm_maskz_madd52lo_epu64(k: __mmask8, a: __m128i, b: __m128i, c: __m128i) } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.vpmadd52l.uq.128"] fn vpmadd52luq_128(z: __m128i, x: __m128i, y: __m128i) -> __m128i; #[link_name = "llvm.x86.avx512.vpmadd52h.uq.128"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs b/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs index d9ad14ef00ddb..141a8c8aec2bc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512vbmi.rs @@ -453,7 +453,7 @@ pub fn _mm_maskz_multishift_epi64_epi8(k: __mmask16, a: __m128i, b: __m128i) -> } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.vpermi2var.qi.512"] fn vpermi2b(a: i8x64, idx: i8x64, b: i8x64) -> i8x64; #[link_name = "llvm.x86.avx512.vpermi2var.qi.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs b/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs index 78a50b90c8614..0a4accc2f70fb 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512vbmi2.rs @@ -2383,7 +2383,7 @@ pub const fn _mm_maskz_shrdi_epi16( } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.mask.compress.store.w.512"] fn vcompressstorew(mem: *mut i8, data: i16x32, mask: u32); #[link_name = "llvm.x86.avx512.mask.compress.store.w.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs b/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs index 8cd8764f24868..b9084aec59344 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512vnni.rs @@ -873,7 +873,7 @@ pub fn _mm256_dpwuuds_epi32(src: __m256i, a: __m256i, b: __m256i) -> __m256i { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.vpdpwssd.512"] fn vpdpwssd(src: i32x16, a: i16x32, b: i16x32) -> i32x16; #[link_name = "llvm.x86.avx512.vpdpwssd.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vp2intersect.rs b/library/stdarch/crates/core_arch/src/x86/avx512vp2intersect.rs index 4dd7412e9e330..30fcfce63ccf4 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512vp2intersect.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512vp2intersect.rs @@ -110,7 +110,7 @@ pub unsafe fn _mm512_2intersect_epi64( } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.vp2intersect.d.128"] fn vp2intersectd_128(a: i32x4, b: i32x4) -> (u8, u8); #[link_name = "llvm.x86.avx512.vp2intersect.q.128"] diff --git a/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs b/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs index 861213eb4257f..b17d3de48b595 100644 --- a/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs +++ b/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs @@ -176,7 +176,7 @@ pub fn _mm256_cvtneps_avx_pbh(a: __m256) -> __m128bh { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.vbcstnebf162ps128"] fn bcstnebf162ps_128(a: *const bf16) -> __m128; #[link_name = "llvm.x86.vbcstnebf162ps256"] diff --git a/library/stdarch/crates/core_arch/src/x86/bmi1.rs b/library/stdarch/crates/core_arch/src/x86/bmi1.rs index 432051abd1cfa..21da03667f849 100644 --- a/library/stdarch/crates/core_arch/src/x86/bmi1.rs +++ b/library/stdarch/crates/core_arch/src/x86/bmi1.rs @@ -131,7 +131,7 @@ pub const fn _mm_tzcnt_32(x: u32) -> i32 { x.trailing_zeros() as i32 } -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.bmi.bextr.32"] fn x86_bmi_bextr_32(x: u32, y: u32) -> u32; } diff --git a/library/stdarch/crates/core_arch/src/x86/bmi2.rs b/library/stdarch/crates/core_arch/src/x86/bmi2.rs index 5320640d96873..dae4133d63bec 100644 --- a/library/stdarch/crates/core_arch/src/x86/bmi2.rs +++ b/library/stdarch/crates/core_arch/src/x86/bmi2.rs @@ -67,7 +67,7 @@ pub fn _pext_u32(a: u32, mask: u32) -> u32 { unsafe { x86_bmi2_pext_32(a, mask) } } -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.bmi.bzhi.32"] fn x86_bmi2_bzhi_32(x: u32, y: u32) -> u32; #[link_name = "llvm.x86.bmi.pdep.32"] diff --git a/library/stdarch/crates/core_arch/src/x86/fxsr.rs b/library/stdarch/crates/core_arch/src/x86/fxsr.rs index 08619efe7c9ef..74a95e192a3af 100644 --- a/library/stdarch/crates/core_arch/src/x86/fxsr.rs +++ b/library/stdarch/crates/core_arch/src/x86/fxsr.rs @@ -4,7 +4,7 @@ use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.fxsave"] fn fxsave(p: *mut u8); #[link_name = "llvm.x86.fxrstor"] diff --git a/library/stdarch/crates/core_arch/src/x86/gfni.rs b/library/stdarch/crates/core_arch/src/x86/gfni.rs index e9ee27a7b823b..8cebd04a4b836 100644 --- a/library/stdarch/crates/core_arch/src/x86/gfni.rs +++ b/library/stdarch/crates/core_arch/src/x86/gfni.rs @@ -23,7 +23,7 @@ use crate::mem::transmute; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.vgf2p8affineinvqb.512"] fn vgf2p8affineinvqb_512(x: i8x64, a: i8x64, imm8: u8) -> i8x64; #[link_name = "llvm.x86.vgf2p8affineinvqb.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs b/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs index 0f2769257f958..454785c5e0c89 100644 --- a/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs +++ b/library/stdarch/crates/core_arch/src/x86/pclmulqdq.rs @@ -11,7 +11,7 @@ use crate::core_arch::x86::__m128i; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.pclmulqdq"] fn pclmulqdq(a: __m128i, round_key: __m128i, imm8: u8) -> __m128i; } diff --git a/library/stdarch/crates/core_arch/src/x86/rtm.rs b/library/stdarch/crates/core_arch/src/x86/rtm.rs index c88bd6592d784..f09b95d76bdb3 100644 --- a/library/stdarch/crates/core_arch/src/x86/rtm.rs +++ b/library/stdarch/crates/core_arch/src/x86/rtm.rs @@ -16,7 +16,7 @@ #[cfg(test)] use stdarch_test::assert_instr; -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.xbegin"] fn x86_xbegin() -> i32; #[link_name = "llvm.x86.xend"] diff --git a/library/stdarch/crates/core_arch/src/x86/sha.rs b/library/stdarch/crates/core_arch/src/x86/sha.rs index f8a3295d19589..f7d8c3c0b2408 100644 --- a/library/stdarch/crates/core_arch/src/x86/sha.rs +++ b/library/stdarch/crates/core_arch/src/x86/sha.rs @@ -1,7 +1,7 @@ use crate::core_arch::{simd::*, x86::*}; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sha1msg1"] fn sha1msg1(a: i32x4, b: i32x4) -> i32x4; #[link_name = "llvm.x86.sha1msg2"] diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index afaaccfbf27f4..e31175d48cf94 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -1987,7 +1987,7 @@ pub const fn _MM_TRANSPOSE4_PS( } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse.rcp.ss"] fn rcpss(a: __m128) -> __m128; #[link_name = "llvm.x86.sse.rcp.ps"] diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index 1f97f3c69d0e3..983d7ff23d39f 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -3236,7 +3236,7 @@ pub const fn _mm_unpacklo_pd(a: __m128d, b: __m128d) -> __m128d { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse2.pause"] fn pause(); #[link_name = "llvm.x86.sse2.clflush"] diff --git a/library/stdarch/crates/core_arch/src/x86/sse3.rs b/library/stdarch/crates/core_arch/src/x86/sse3.rs index e4c75702544d9..2f6fa35cb616a 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse3.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse3.rs @@ -178,7 +178,7 @@ pub const fn _mm_moveldup_ps(a: __m128) -> __m128 { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse3.ldu.dq"] fn lddqu(mem_addr: *const i8) -> i8x16; } diff --git a/library/stdarch/crates/core_arch/src/x86/sse41.rs b/library/stdarch/crates/core_arch/src/x86/sse41.rs index 4ebf7d3bd39a8..d981166ff08c9 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse41.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse41.rs @@ -1181,7 +1181,7 @@ pub unsafe fn _mm_stream_load_si128(mem_addr: *const __m128i) -> __m128i { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse41.insertps"] fn insertps(a: __m128, b: __m128, imm8: u8) -> __m128; #[link_name = "llvm.x86.sse41.dppd"] diff --git a/library/stdarch/crates/core_arch/src/x86/sse42.rs b/library/stdarch/crates/core_arch/src/x86/sse42.rs index 55e22592637f1..0534fe9379a18 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse42.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse42.rs @@ -569,7 +569,7 @@ pub const fn _mm_cmpgt_epi64(a: __m128i, b: __m128i) -> __m128i { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { // SSE 4.2 string and text comparison ops #[link_name = "llvm.x86.sse42.pcmpestrm128"] fn pcmpestrm128(a: i8x16, la: i32, b: i8x16, lb: i32, imm8: i8) -> u8x16; diff --git a/library/stdarch/crates/core_arch/src/x86/sse4a.rs b/library/stdarch/crates/core_arch/src/x86/sse4a.rs index f36b879a030e3..14e9b56dcb2ed 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse4a.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse4a.rs @@ -6,7 +6,7 @@ use crate::core_arch::{simd::*, x86::*}; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse4a.extrq"] fn extrq(x: i64x2, y: i8x16) -> i64x2; #[link_name = "llvm.x86.sse4a.extrqi"] diff --git a/library/stdarch/crates/core_arch/src/x86/ssse3.rs b/library/stdarch/crates/core_arch/src/x86/ssse3.rs index 1d7a97944a37b..b0152c81596bd 100644 --- a/library/stdarch/crates/core_arch/src/x86/ssse3.rs +++ b/library/stdarch/crates/core_arch/src/x86/ssse3.rs @@ -345,7 +345,7 @@ pub fn _mm_sign_epi32(a: __m128i, b: __m128i) -> __m128i { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.ssse3.pshuf.b.128"] fn pshufb128(a: u8x16, b: u8x16) -> u8x16; diff --git a/library/stdarch/crates/core_arch/src/x86/tbm.rs b/library/stdarch/crates/core_arch/src/x86/tbm.rs index 0ba4572dcd029..2a44579408364 100644 --- a/library/stdarch/crates/core_arch/src/x86/tbm.rs +++ b/library/stdarch/crates/core_arch/src/x86/tbm.rs @@ -13,7 +13,7 @@ #[cfg(test)] use stdarch_test::assert_instr; -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.tbm.bextri.u32"] fn bextri_u32(a: u32, control: u32) -> u32; } diff --git a/library/stdarch/crates/core_arch/src/x86/vaes.rs b/library/stdarch/crates/core_arch/src/x86/vaes.rs index 864b1d56d1057..72dd387f900d5 100644 --- a/library/stdarch/crates/core_arch/src/x86/vaes.rs +++ b/library/stdarch/crates/core_arch/src/x86/vaes.rs @@ -14,7 +14,7 @@ use crate::core_arch::x86::__m512i; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.aesni.aesenc.256"] fn aesenc_256(a: __m256i, round_key: __m256i) -> __m256i; #[link_name = "llvm.x86.aesni.aesenclast.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs b/library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs index ad44e59f3ada1..4c39ae6ee7aa3 100644 --- a/library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs +++ b/library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs @@ -12,7 +12,7 @@ use crate::core_arch::x86::__m512i; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.pclmulqdq.256"] fn pclmulqdq_256(a: __m256i, round_key: __m256i, imm8: u8) -> __m256i; #[link_name = "llvm.x86.pclmulqdq.512"] diff --git a/library/stdarch/crates/core_arch/src/x86/xsave.rs b/library/stdarch/crates/core_arch/src/x86/xsave.rs index e22d3580ff463..395e2c64be3a0 100644 --- a/library/stdarch/crates/core_arch/src/x86/xsave.rs +++ b/library/stdarch/crates/core_arch/src/x86/xsave.rs @@ -5,7 +5,7 @@ use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.xsave"] fn xsave(p: *mut u8, hi: u32, lo: u32); #[link_name = "llvm.x86.xrstor"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/amx.rs b/library/stdarch/crates/core_arch/src/x86_64/amx.rs index 08585d2067c15..2e46e50f9ff9b 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/amx.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/amx.rs @@ -595,7 +595,7 @@ pub unsafe fn _tile_movrowi() -> __m512i { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.ldtilecfg"] fn ldtilecfg(mem_addr: *const u8); #[link_name = "llvm.x86.sttilecfg"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs index 0fd9b09363d4b..e26bfc5c1ca4f 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs @@ -527,7 +527,7 @@ pub fn _mm_cvtt_roundss_u64(a: __m128) -> u64 { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512.vcvtss2si64"] fn vcvtss2si64(a: f32x4, rounding: i32) -> i64; #[link_name = "llvm.x86.avx512.vcvtss2usi64"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs index 2a511328bb382..5baf1c9036e19 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs @@ -211,7 +211,7 @@ pub fn _mm_cvtt_roundsh_u64(a: __m128h) -> u64 { } #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.avx512fp16.vcvtsi642sh"] fn vcvtsi642sh(a: __m128h, b: i64, rounding: i32) -> __m128h; #[link_name = "llvm.x86.avx512fp16.vcvtusi642sh"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/bmi.rs b/library/stdarch/crates/core_arch/src/x86_64/bmi.rs index 8d2b22089ac10..f082953f9df90 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/bmi.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/bmi.rs @@ -122,7 +122,7 @@ pub const fn _mm_tzcnt_64(x: u64) -> i64 { x.trailing_zeros() as i64 } -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.bmi.bextr.64"] fn x86_bmi_bextr_64(x: u64, y: u64) -> u64; } diff --git a/library/stdarch/crates/core_arch/src/x86_64/bmi2.rs b/library/stdarch/crates/core_arch/src/x86_64/bmi2.rs index 6151eee8bdbb5..81ab9e05add96 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/bmi2.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/bmi2.rs @@ -69,7 +69,7 @@ pub fn _pext_u64(a: u64, mask: u64) -> u64 { unsafe { x86_bmi2_pext_64(a, mask) } } -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.bmi.bzhi.64"] fn x86_bmi2_bzhi_64(x: u64, y: u64) -> u64; #[link_name = "llvm.x86.bmi.pdep.64"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs b/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs index 28bf1951167a5..f50dacb4bee4f 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs @@ -4,7 +4,7 @@ use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.fxsave64"] fn fxsave64(p: *mut u8); #[link_name = "llvm.x86.fxrstor64"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/sse.rs b/library/stdarch/crates/core_arch/src/x86_64/sse.rs index 81e1070b55691..521652c126914 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/sse.rs @@ -6,7 +6,7 @@ use crate::core_arch::x86::*; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse.cvtss2si64"] fn cvtss2si64(a: __m128) -> i64; #[link_name = "llvm.x86.sse.cvttss2si64"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/sse2.rs b/library/stdarch/crates/core_arch/src/x86_64/sse2.rs index 08dabf053d428..c4768cedbfa6b 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/sse2.rs @@ -6,7 +6,7 @@ use crate::core_arch::x86::*; use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse2.cvtsd2si64"] fn cvtsd2si64(a: __m128d) -> i64; #[link_name = "llvm.x86.sse2.cvttsd2si64"] diff --git a/library/stdarch/crates/core_arch/src/x86_64/sse42.rs b/library/stdarch/crates/core_arch/src/x86_64/sse42.rs index cd32c149aff5b..307e6167aabae 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/sse42.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/sse42.rs @@ -4,7 +4,7 @@ use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.sse42.crc32.64.64"] fn crc32_64_64(crc: u64, v: u64) -> u64; } diff --git a/library/stdarch/crates/core_arch/src/x86_64/tbm.rs b/library/stdarch/crates/core_arch/src/x86_64/tbm.rs index fe12538b07a06..b4ec50a66fa0b 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/tbm.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/tbm.rs @@ -13,7 +13,7 @@ #[cfg(test)] use stdarch_test::assert_instr; -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.tbm.bextri.u64"] fn bextri_u64(a: u64, control: u64) -> u64; } diff --git a/library/stdarch/crates/core_arch/src/x86_64/xsave.rs b/library/stdarch/crates/core_arch/src/x86_64/xsave.rs index 30a7123315e5f..c307d40073433 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/xsave.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/xsave.rs @@ -6,7 +6,7 @@ use stdarch_test::assert_instr; #[allow(improper_ctypes)] -unsafe extern "C" { +unsafe extern "unadjusted" { #[link_name = "llvm.x86.xsave64"] fn xsave64(p: *mut u8, hi: u32, lo: u32); #[link_name = "llvm.x86.xrstor64"] From fe9d6fe6f2e0db1dde6bdce709e6c863fc43a095 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 3 Jun 2026 22:03:14 +0200 Subject: [PATCH 05/77] test that even ZST references prevent deallocation via child pointers --- .../src/borrow_tracker/tree_borrows/tree.rs | 4 +- .../deallocate_against_protector1.rs | 6 ++- ...eallocate_against_protector1.stack.stderr} | 8 ++-- .../deallocate_against_protector1.tree.stderr | 40 +++++++++++++++++++ .../deallocate_against_protector2.rs | 23 +++++++++++ ...deallocate_against_protector2.stack.stderr | 27 +++++++++++++ .../deallocate_against_protector2.tree.stderr | 29 ++++++++++++++ 7 files changed, 131 insertions(+), 6 deletions(-) rename src/tools/miri/tests/fail/{stacked_borrows => both_borrows}/deallocate_against_protector1.rs (50%) rename src/tools/miri/tests/fail/{stacked_borrows/deallocate_against_protector1.stderr => both_borrows/deallocate_against_protector1.stack.stderr} (76%) create mode 100644 src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.tree.stderr create mode 100644 src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.rs create mode 100644 src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.stack.stderr create mode 100644 src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.tree.stderr diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 296de803d5828..b58a7cfeba92e 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -574,7 +574,9 @@ impl<'tcx> Tree { // Don't check for protector if it is a Cell (see `unsafe_cell_deallocate` in `interior_mutability.rs`). // Related to https://github.com/rust-lang/rust/issues/55005. && !perm.permission.is_cell() - // Only trigger UB if the accessed bit is set, i.e. if the protector is actually protecting this offset. See #4579. + // Only trigger UB if the accessed bit is set, i.e. if the protector + // is actually protecting this offset. See #4579. Note that this + // takes into account the access we just did above! && perm.accessed { Err(TbError { diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.rs similarity index 50% rename from src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs rename to src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.rs index a34df7c7fe3ae..211d74caadd8a 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.rs +++ b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.rs @@ -1,4 +1,8 @@ -//@error-in-other-file: /deallocating while item \[Unique for .*\] is strongly protected/ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows + +//@[stack]error-in-other-file: /deallocating while item \[Unique for .*\] is strongly protected/ +//@[tree]error-in-other-file: /deallocation through .* is forbidden/ fn inner(x: &mut i32, f: fn(&mut i32)) { // `f` may mutate, but it may not deallocate! diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.stack.stderr similarity index 76% rename from src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr rename to src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.stack.stderr index 9f0df14ee4ddd..b8a763a5fc3f4 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.stack.stderr @@ -14,13 +14,13 @@ LL | self.1.deallocate(From::from(ptr.cast()), layout); 2: std::mem::drop::> at RUSTLIB/core/src/mem/mod.rs:LL:CC 3: main::{closure#0} - at tests/fail/stacked_borrows/deallocate_against_protector1.rs:LL:CC - 4: <{closure@tests/fail/stacked_borrows/deallocate_against_protector1.rs:LL:CC} as std::ops::FnOnce<(&mut i32,)>>::call_once - shim + at tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC + 4: <{closure@tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC} as std::ops::FnOnce<(&mut i32,)>>::call_once - shim at RUSTLIB/core/src/ops/function.rs:LL:CC 5: inner - at tests/fail/stacked_borrows/deallocate_against_protector1.rs:LL:CC + at tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC 6: main - at tests/fail/stacked_borrows/deallocate_against_protector1.rs:LL:CC + at tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.tree.stderr new file mode 100644 index 0000000000000..3e97a15333ac6 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector1.tree.stderr @@ -0,0 +1,40 @@ +error: Undefined Behavior: deallocation through at ALLOC[0x0] is forbidden + --> RUSTLIB/alloc/src/boxed.rs:LL:CC + | +LL | self.1.deallocate(From::from(ptr.cast()), layout); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the allocation of the accessed tag also contains the strongly protected tag + = help: the strongly protected tag disallows deallocations +help: the accessed tag was created here + --> tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC + | +LL | drop(unsafe { Box::from_raw(raw) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: the strongly protected tag was created here, in the initial state Reserved + --> tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC + | +LL | inner(Box::leak(Box::new(0)), |x| { + | ^ + = note: stack backtrace: + 0: as std::ops::Drop>::drop + at RUSTLIB/alloc/src/boxed.rs:LL:CC + 1: std::ptr::drop_glue::> - shim(Some(std::boxed::Box)) + at RUSTLIB/core/src/ptr/mod.rs:LL:CC + 2: std::mem::drop::> + at RUSTLIB/core/src/mem/mod.rs:LL:CC + 3: main::{closure#0} + at tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC + 4: <{closure@tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC} as std::ops::FnOnce<(&mut i32,)>>::call_once - shim + at RUSTLIB/core/src/ops/function.rs:LL:CC + 5: inner + at tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC + 6: main + at tests/fail/both_borrows/deallocate_against_protector1.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.rs b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.rs new file mode 100644 index 0000000000000..4cac0cdd03f8b --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.rs @@ -0,0 +1,23 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows + +// Ensure that even a ZST prevents the reference from being used for deallocation. +// The `nofree` attributes we add in LLVM IR rely on this. + +use std::alloc::Layout; + +fn inner(x: &mut (), f: fn(&mut ())) { + // `f` may mutate, but it may not deallocate! + f(x) +} + +fn main() { + let ptr = Box::leak(Box::new(0i32)) as *mut i32; + inner(unsafe { &mut *(ptr as *mut ()) }, |x| unsafe { + let raw = x as *mut _ as *mut i32; + // Avoid ever creating a `Box`, we don't want any implicit accesses. + std::alloc::dealloc(raw.cast(), Layout::new::()); + //~[tree]^ERROR: /deallocation through .* is forbidden/ + //~[stack]|ERROR: tag does not exist in the borrow stack for this location + }); +} diff --git a/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.stack.stderr new file mode 100644 index 0000000000000..20993ef5072b1 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.stack.stderr @@ -0,0 +1,27 @@ +error: Undefined Behavior: attempting deallocation using at ALLOC, but that tag does not exist in the borrow stack for this location + --> tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + | +LL | std::alloc::dealloc(raw.cast(), Layout::new::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere + --> tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + | +LL | let raw = x as *mut _ as *mut i32; + | ^ + = note: stack backtrace: + 0: main::{closure#0} + at tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + 1: <{closure@tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC} as std::ops::FnOnce<(&mut (),)>>::call_once - shim + at RUSTLIB/core/src/ops/function.rs:LL:CC + 2: inner + at tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + 3: main + at tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.tree.stderr new file mode 100644 index 0000000000000..7fae0b6a07773 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/deallocate_against_protector2.tree.stderr @@ -0,0 +1,29 @@ +error: Undefined Behavior: deallocation through at ALLOC[0x0] is forbidden + --> tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + | +LL | std::alloc::dealloc(raw.cast(), Layout::new::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the allocation of the accessed tag also contains the strongly protected tag + = help: the strongly protected tag disallows deallocations +help: the strongly protected tag was created here, in the initial state Reserved + --> tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + | +LL | inner(unsafe { &mut *(ptr as *mut ()) }, |x| unsafe { + | ^ + = note: stack backtrace: + 0: main::{closure#0} + at tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + 1: <{closure@tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC} as std::ops::FnOnce<(&mut (),)>>::call_once - shim + at RUSTLIB/core/src/ops/function.rs:LL:CC + 2: inner + at tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + 3: main + at tests/fail/both_borrows/deallocate_against_protector2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From a44451731d6c3fe201fd386456eb6893c440d9af Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 8 Jun 2026 05:38:35 +0000 Subject: [PATCH 06/77] Prepare for merging from rust-lang/rust This updates the rust-version file to 029c9e18dd1f4668e1d42bb187c1c263dfe20093. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 59e9e5a0e6ee9..387bd8edd2196 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -045b17737dab5fcc28e4cbee0cfe2ce4ed363b32 +029c9e18dd1f4668e1d42bb187c1c263dfe20093 From 1709e202159338953dbd0134d589e55bd2a76152 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 9 Jun 2026 12:42:11 +0100 Subject: [PATCH 07/77] intrinsic-test: remove now-unnecessary feat attr --- library/stdarch/crates/intrinsic-test/src/arm/config.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/config.rs b/library/stdarch/crates/intrinsic-test/src/arm/config.rs index 87b8ebfa183e7..7c26143622e71 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/config.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/config.rs @@ -9,7 +9,6 @@ pub const PLATFORM_RUST_CFGS: &str = r#" #![cfg_attr(target_arch = "arm", feature(stdarch_arm_neon_intrinsics))] #![cfg_attr(target_arch = "arm", feature(stdarch_aarch32_crc32))] #![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_fcma))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_dotprod))] #![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_i8mm))] #![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_sm4))] #![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_ftts))] From 9b80946bc0c0d962e3a7e66d100d29c2155ae7de Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Thu, 11 Jun 2026 19:55:05 +0800 Subject: [PATCH 08/77] loongarch: Remove explicit zero-extension from CRC[C].W.{B,H}.W The CRC[C].W.{B,H}.W only consume the low 8/16 bits of the input operand. The previous unsigned cast was a workaround for Miri's software implementation. Miri now masks the inputs to match hardware semantics, and LLVM will learn the demanded-bits property of CRC intrinsics, so the explicit zero-extension is no longer required. --- library/stdarch/crates/core_arch/src/loongarch64/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/loongarch64/mod.rs b/library/stdarch/crates/core_arch/src/loongarch64/mod.rs index 7e9f45f5e7b04..05a2f9a39ff0e 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/mod.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/mod.rs @@ -64,14 +64,14 @@ unsafe extern "unadjusted" { #[inline(always)] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn crc_w_b_w(a: i8, b: i32) -> i32 { - unsafe { __crc_w_b_w(a.cast_unsigned() as i32, b) } + unsafe { __crc_w_b_w(a as i32, b) } } /// Calculate the CRC value using the IEEE 802.3 polynomial (0xEDB88320) #[inline(always)] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn crc_w_h_w(a: i16, b: i32) -> i32 { - unsafe { __crc_w_h_w(a.cast_unsigned() as i32, b) } + unsafe { __crc_w_h_w(a as i32, b) } } /// Calculate the CRC value using the IEEE 802.3 polynomial (0xEDB88320) @@ -92,14 +92,14 @@ pub fn crc_w_d_w(a: i64, b: i32) -> i32 { #[inline(always)] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn crcc_w_b_w(a: i8, b: i32) -> i32 { - unsafe { __crcc_w_b_w(a.cast_unsigned() as i32, b) } + unsafe { __crcc_w_b_w(a as i32, b) } } /// Calculate the CRC value using the Castagnoli polynomial (0x82F63B78) #[inline(always)] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn crcc_w_h_w(a: i16, b: i32) -> i32 { - unsafe { __crcc_w_h_w(a.cast_unsigned() as i32, b) } + unsafe { __crcc_w_h_w(a as i32, b) } } /// Calculate the CRC value using the Castagnoli polynomial (0x82F63B78) From 1d67d0d8ccd0913eb4326212cc3f79bec7745594 Mon Sep 17 00:00:00 2001 From: Ruy Rocha <108208+ruyrocha@users.noreply.github.com> Date: Thu, 4 Jun 2026 15:42:04 -0300 Subject: [PATCH 09/77] Update rand to 0.9.3 to fix GHSA-cq8v-f236-94qc --- library/stdarch/Cargo.lock | 50 +++++++++---------- .../crates/stdarch-gen-loongarch/Cargo.toml | 2 +- library/stdarch/examples/Cargo.toml | 2 +- library/stdarch/examples/connect5.rs | 4 +- library/stdarch/examples/hex.rs | 4 +- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index a1c31fa9f0cea..804879c8fdc6a 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -282,13 +282,14 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "getrandom" -version = "0.2.17" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi 5.3.0", + "wasip2", ] [[package]] @@ -299,7 +300,7 @@ checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.0", "wasip2", "wasip3", @@ -529,7 +530,7 @@ checksum = "95c589f335db0f6aaa168a7cd27b1fc6920f5e1470c804f814d9cd6e62a0f70b" dependencies = [ "env_logger 0.11.10", "log", - "rand 0.10.0", + "rand 0.10.1", ] [[package]] @@ -541,6 +542,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r-efi" version = "6.0.0" @@ -549,20 +556,19 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core 0.9.5", ] [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "getrandom 0.4.2", "rand_core 0.10.0", @@ -570,21 +576,21 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core 0.9.5", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.2.17", + "getrandom 0.3.4", ] [[package]] @@ -805,7 +811,7 @@ dependencies = [ name = "stdarch-gen-loongarch" version = "0.1.0" dependencies = [ - "rand 0.8.5", + "rand 0.9.4", ] [[package]] @@ -838,7 +844,7 @@ version = "0.0.0" dependencies = [ "core_arch", "quickcheck", - "rand 0.8.5", + "rand 0.9.4", ] [[package]] @@ -921,12 +927,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "wasip2" version = "1.0.2+wasi-0.2.9" diff --git a/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml b/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml index d3ac607c5576c..1a8c052ebe318 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml @@ -7,4 +7,4 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.5" +rand = "0.9.3" diff --git a/library/stdarch/examples/Cargo.toml b/library/stdarch/examples/Cargo.toml index c4fc4c7e374c8..8752f206526c7 100644 --- a/library/stdarch/examples/Cargo.toml +++ b/library/stdarch/examples/Cargo.toml @@ -13,7 +13,7 @@ default-run = "hex" [dependencies] core_arch = { path = "../crates/core_arch" } quickcheck = "1.0" -rand = "0.8" +rand = "0.9.3" [[bin]] name = "hex" diff --git a/library/stdarch/examples/connect5.rs b/library/stdarch/examples/connect5.rs index f24657b148394..2df294b16b71e 100644 --- a/library/stdarch/examples/connect5.rs +++ b/library/stdarch/examples/connect5.rs @@ -33,8 +33,8 @@ #![cfg_attr(target_arch = "x86_64", feature(stdarch_internal))] #![feature(stmt_expr_attributes)] +use rand::rng; use rand::seq::SliceRandom; -use rand::thread_rng; use std::cmp; use std::time::Instant; @@ -374,7 +374,7 @@ impl List { } pub fn shuffle(&mut self) { - let mut rng = thread_rng(); + let mut rng = rng(); let num = self.p_size as usize; self.p_move[..num].shuffle(&mut rng); diff --git a/library/stdarch/examples/hex.rs b/library/stdarch/examples/hex.rs index 21827b375adaf..6417562074d9c 100644 --- a/library/stdarch/examples/hex.rs +++ b/library/stdarch/examples/hex.rs @@ -354,9 +354,9 @@ mod benches { len: usize, f: for<'a> unsafe fn(&[u8], &'a mut [u8]) -> Result<&'a str, usize>, ) { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let input = std::iter::repeat(()) - .map(|()| rng.r#gen::()) + .map(|()| rng.r#random::()) .take(len) .collect::>(); let mut dst = vec![0; input.len() * 2]; From e5c59b3016d8f3ae7b41e7e1c389b08c41df1881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Mon, 25 May 2026 21:36:18 +0200 Subject: [PATCH 10/77] libc: Minimal support for `mprotect` and `madvise` We still only support `PROT_READ|PROT_WRITE`, so `mprotect` is a no-op other than validating arguments. We only implement `madvise` for the hints that can be ignored without a change in semantic (e.g. no `MADV_DONTNEED`, so it is also a no-op other than validating arguments. --- .../miri/src/shims/unix/foreign_items.rs | 38 +++++- src/tools/miri/src/shims/unix/mem.rs | 125 +++++++++++++++--- .../fail-dep/libc/madvise_out_of_bounds.rs | 20 +++ .../libc/madvise_out_of_bounds.stderr | 13 ++ .../fail-dep/libc/mprotect_out_of_bounds.rs | 20 +++ .../libc/mprotect_out_of_bounds.stderr | 13 ++ src/tools/miri/tests/pass-dep/libc/mmap.rs | 74 +++++++++++ 7 files changed, 278 insertions(+), 25 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.stderr create mode 100644 src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.stderr diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index fa2af98b9fc8d..e7aa80d279d15 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -816,18 +816,46 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "mmap" => { - let [addr, length, prot, flags, fd, offset] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; + let [addr, length, prot, flags, fd, offset] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, usize, i32, i32, i32, libc::off_t) -> *mut _), + link_name, + abi, + args, + )?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let ptr = this.mmap(addr, length, prot, flags, fd, offset)?; this.write_scalar(ptr, dest)?; } "munmap" => { - let [addr, length] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; + let [addr, length] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, usize) -> i32), + link_name, + abi, + args, + )?; let result = this.munmap(addr, length)?; this.write_scalar(result, dest)?; } + "mprotect" => { + let [addr, length, prot] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, usize, i32) -> i32), + link_name, + abi, + args, + )?; + let result = this.mprotect(addr, length, prot)?; + this.write_scalar(result, dest)?; + } + "madvise" => { + let [addr, length, advice] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, usize, i32) -> i32), + link_name, + abi, + args, + )?; + let result = this.madvise(addr, length, advice)?; + this.write_scalar(result, dest)?; + } "reallocarray" => { // Currently this function does not exist on all Unixes, e.g. on macOS. @@ -1386,7 +1414,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } - "sigaction" | "mprotect" if this.frame_in_std() => { + "sigaction" if this.frame_in_std() => { let [_, _, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs index c2ad7c0e9d0ab..50be3c7ae15e6 100644 --- a/src/tools/miri/src/shims/unix/mem.rs +++ b/src/tools/miri/src/shims/unix/mem.rs @@ -53,9 +53,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(Scalar::from_maybe_pointer(Pointer::without_provenance(addr), this)); } - let prot_read = this.eval_libc_i32("PROT_READ"); - let prot_write = this.eval_libc_i32("PROT_WRITE"); - // First, we do some basic argument validation as required by mmap if (flags & (map_private | map_shared)).count_ones() != 1 { this.set_last_error(LibcError("EINVAL"))?; @@ -80,13 +77,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } - // Miri doesn't support protections other than PROT_READ|PROT_WRITE. - if prot != prot_read | prot_write { - throw_unsup_format!( - "Miri does not support calls to mmap with protections other than \ - PROT_READ|PROT_WRITE", - ); - } + verify_prot(this, prot)?; // Miri does not support shared mappings, or any of the other extensions that for example // Linux has added to the flags arguments. @@ -103,14 +94,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let align = this.machine.page_align(); - let Some(map_length) = length.checked_next_multiple_of(this.machine.page_size) else { + let Some(map_length) = round_up_to_page_size(this, length) else { this.set_last_error(LibcError("EINVAL"))?; return interp_ok(this.eval_libc("MAP_FAILED")); }; - if map_length > this.target_usize_max() { - this.set_last_error(LibcError("EINVAL"))?; - return interp_ok(this.eval_libc("MAP_FAILED")); - } let ptr = this.allocate_ptr( Size::from_bytes(map_length), @@ -135,13 +122,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); } - let Some(length) = length.checked_next_multiple_of(this.machine.page_size) else { + let Some(length) = round_up_to_page_size(this, length) else { return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); }; - if length > this.target_usize_max() { - this.set_last_error(LibcError("EINVAL"))?; - return interp_ok(this.eval_libc("MAP_FAILED")); - } let length = Size::from_bytes(length); this.deallocate_ptr( @@ -152,4 +135,106 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(0)) } + + fn mprotect( + &mut self, + addr: &OpTy<'tcx>, + length: &OpTy<'tcx>, + prot: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let addr = this.read_pointer(addr)?; + let length = this.read_target_usize(length)?; + let prot = this.read_scalar(prot)?.to_i32()?; + + // addr must be a multiple of the page size. + if !addr.addr().bytes().is_multiple_of(this.machine.page_size) { + return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); + } + + verify_prot(this, prot)?; + + // The pages from `[addr, addr + length)` must be mapped, so length definitely must not overflow. + let Some(length) = round_up_to_page_size(this, length) else { + return this.set_errno_and_return_neg1_i32(LibcError("ENOMEM")); + }; + // Ensure this is actually allocated memory we can access. + this.check_ptr_access(addr, Size::from_bytes(length), CheckInAllocMsg::MemoryAccess) + .map_err_kind(|_| err_ub_format!("`mprotect` called on out-of-bounds memory"))?; + + // If the memory comes from memory the Rust program has allocated with mmap, we only support + // `PROT_READ|PROT_WRITE`, so this `mprotect` is a no-op. If the memory was mmaped by the + // runtime (e.g. if it's the stack, executable memory, or static memory), POSIX also allows + // us to remap it. In those cases, such a call to `PROT_READ|PROT_WRITE` might actually change the permissions, + // but treating them as the new permissions is still UB. Therefore, we just pretend that we + // did the permission change by returning success, and will still reject if you try to use + // it with the "new" permissions. + interp_ok(Scalar::from_i32(0)) + } + + fn madvise( + &mut self, + addr: &OpTy<'tcx>, + length: &OpTy<'tcx>, + advice: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let addr = this.read_pointer(addr)?; + let length = this.read_target_usize(length)?; + let advise = this.read_scalar(advice)?.to_i32()?; + + // addr must be a multiple of the page size. + if !addr.addr().bytes().is_multiple_of(this.machine.page_size) { + return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); + } + + // advise must be supported. + let madv_normal = this.eval_libc_i32("MADV_NORMAL"); + let madv_random = this.eval_libc_i32("MADV_RANDOM"); + let madv_sequential = this.eval_libc_i32("MADV_SEQUENTIAL"); + let madv_willneed = this.eval_libc_i32("MADV_WILLNEED"); + if advise != madv_normal + && advise != madv_random + && advise != madv_sequential + && advise != madv_willneed + { + throw_unsup_format!( + "Miri does not support calls to madvise with advice other than MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL, or MADV_WILLNEED", + ); + } + + // The pages from `[addr, addr + length)` must be mapped, so length definitely must not overflow. + let Some(length) = round_up_to_page_size(this, length) else { + return this.set_errno_and_return_neg1_i32(LibcError("ENOMEM")); + }; + // Ensure this is actually allocated memory we can access. + this.check_ptr_access(addr, Size::from_bytes(length), CheckInAllocMsg::MemoryAccess) + .map_err_kind(|_| err_ub_format!("`madvise` called on out-of-bounds memory"))?; + + // All advises we support are no-ops. + interp_ok(Scalar::from_i32(0)) + } +} + +fn round_up_to_page_size(this: &MiriInterpCx<'_>, length: u64) -> Option { + length + .checked_next_multiple_of(this.machine.page_size) + .filter(|length| *length <= this.target_isize_max().try_into().unwrap()) +} + +fn verify_prot<'tcx>(this: &mut MiriInterpCx<'tcx>, prot: i32) -> InterpResult<'tcx> { + let prot_read = this.eval_libc_i32("PROT_READ"); + let prot_write = this.eval_libc_i32("PROT_WRITE"); + + // Miri doesn't support protections other than PROT_READ|PROT_WRITE. + if prot != prot_read | prot_write { + throw_unsup_format!( + "Miri does not support calls to mmap/mprotect with protections other than \ + PROT_READ|PROT_WRITE", + ); + } + + interp_ok(()) } diff --git a/src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.rs b/src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.rs new file mode 100644 index 0000000000000..29d804fd0d99a --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.rs @@ -0,0 +1,20 @@ +//@compile-flags: -Zmiri-disable-isolation +//@ignore-target: windows # No mmap on Windows +//@normalize-stderr-test: "only .*? bytes" -> "only SIZE bytes" + +fn main() { + unsafe { + let page_size = page_size::get(); + let ptr = libc::mmap( + std::ptr::null_mut(), + page_size, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ); + assert!(!ptr.is_null()); + + libc::madvise(ptr, page_size + 1, libc::MADV_NORMAL); //~ ERROR: `madvise` called on out-of-bounds memory + } +} diff --git a/src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.stderr b/src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.stderr new file mode 100644 index 0000000000000..dbf38c7e4dd0f --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/madvise_out_of_bounds.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: `madvise` called on out-of-bounds memory + --> tests/fail-dep/libc/madvise_out_of_bounds.rs:LL:CC + | +LL | libc::madvise(ptr, page_size + 1, libc::MADV_NORMAL); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.rs b/src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.rs new file mode 100644 index 0000000000000..1e6868b714a81 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.rs @@ -0,0 +1,20 @@ +//@compile-flags: -Zmiri-disable-isolation +//@ignore-target: windows # No mmap on Windows +//@normalize-stderr-test: "only .*? bytes" -> "only SIZE bytes" + +fn main() { + unsafe { + let page_size = page_size::get(); + let ptr = libc::mmap( + std::ptr::null_mut(), + page_size, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ); + assert!(!ptr.is_null()); + + libc::mprotect(ptr, page_size + 1, libc::PROT_READ | libc::PROT_WRITE); //~ ERROR: `mprotect` called on out-of-bounds memory + } +} diff --git a/src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.stderr b/src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.stderr new file mode 100644 index 0000000000000..ac48880150486 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/mprotect_out_of_bounds.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: `mprotect` called on out-of-bounds memory + --> tests/fail-dep/libc/mprotect_out_of_bounds.rs:LL:CC + | +LL | libc::mprotect(ptr, page_size + 1, libc::PROT_READ | libc::PROT_WRITE); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass-dep/libc/mmap.rs b/src/tools/miri/tests/pass-dep/libc/mmap.rs index bfd840d2fb89d..692b59d443ae8 100644 --- a/src/tools/miri/tests/pass-dep/libc/mmap.rs +++ b/src/tools/miri/tests/pass-dep/libc/mmap.rs @@ -94,6 +94,78 @@ fn test_mmap( assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); } +fn test_mprotect() { + let page_size = page_size::get(); + let ptr = unsafe { + libc::mmap( + ptr::null_mut(), + 4 * page_size, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + Default::default(), + ) + }; + assert!(!ptr.is_null()); + + // Protect part of it redundantly. + let res = unsafe { + libc::mprotect(ptr.byte_add(2 * page_size), 42, libc::PROT_READ | libc::PROT_WRITE) + }; + assert_eq!(res, 0i32); + + // Protect everything redundantly. + let res = unsafe { libc::mprotect(ptr, 4 * page_size, libc::PROT_READ | libc::PROT_WRITE) }; + assert_eq!(res, 0i32); + + // We report an error when the address is not a multiple of the page size. + let res = + unsafe { libc::mprotect(ptr.byte_add(11), page_size, libc::PROT_READ | libc::PROT_WRITE) }; + assert_eq!(res, -1); + assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); + + // We report an error if the length cannot be rounded up to a multiple of the page size. + let res = unsafe { libc::mprotect(ptr, usize::MAX - 1, libc::PROT_READ | libc::PROT_WRITE) }; + assert_eq!(res, -1); + assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::ENOMEM); +} + +fn test_madvise() { + let page_size = page_size::get(); + let ptr = unsafe { + libc::mmap( + ptr::null_mut(), + 4 * page_size, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + Default::default(), + ) + }; + assert!(!ptr.is_null()); + + for advice in [libc::MADV_NORMAL, libc::MADV_RANDOM, libc::MADV_SEQUENTIAL, libc::MADV_WILLNEED] + { + // Advise part of it redundantly. + let res = unsafe { libc::madvise(ptr.byte_add(2 * page_size), 42, advice) }; + assert_eq!(res, 0i32); + + // Protect everything redundantly. + let res = unsafe { libc::madvise(ptr, 4 * page_size, advice) }; + assert_eq!(res, 0i32); + } + + // We report an error when the address is not a multiple of the page size. + let res = unsafe { libc::madvise(ptr.byte_add(11), page_size, libc::MADV_NORMAL) }; + assert_eq!(res, -1); + assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); + + // We report an error if the length cannot be rounded up to a multiple of the page size. + let res = unsafe { libc::madvise(ptr, usize::MAX - 1, libc::MADV_NORMAL) }; + assert_eq!(res, -1); + assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::ENOMEM); +} + #[cfg(target_os = "linux")] fn test_mremap() { let page_size = page_size::get(); @@ -145,6 +217,8 @@ fn main() { test_mmap(libc::mmap); #[cfg(target_os = "linux")] test_mmap(libc::mmap64); + test_mprotect(); + test_madvise(); #[cfg(target_os = "linux")] test_mremap(); } From 3f5f9818547d15991d589dc63248836ac2ee8cb5 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 1 Jun 2026 12:44:41 +0000 Subject: [PATCH 11/77] arm-intrinsics: `svget{2,3,4}` These intrinsics need `Arguments_Preparation` added so that the intrinsic-test tool knows to generate const arguments. --- .../intrinsics_data/arm_intrinsics.json | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/library/stdarch/intrinsics_data/arm_intrinsics.json b/library/stdarch/intrinsics_data/arm_intrinsics.json index fab6da7f2c16c..582de29741587 100644 --- a/library/stdarch/intrinsics_data/arm_intrinsics.json +++ b/library/stdarch/intrinsics_data/arm_intrinsics.json @@ -51174,6 +51174,12 @@ "svfloat16x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svfloat16_t" }, @@ -51188,6 +51194,12 @@ "svfloat32x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svfloat32_t" }, @@ -51202,6 +51214,12 @@ "svfloat64x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svfloat64_t" }, @@ -51216,6 +51234,12 @@ "svint16x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint16_t" }, @@ -51230,6 +51254,12 @@ "svint32x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint32_t" }, @@ -51244,6 +51274,12 @@ "svint64x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint64_t" }, @@ -51258,6 +51294,12 @@ "svint8x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint8_t" }, @@ -51272,6 +51314,12 @@ "svuint16x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint16_t" }, @@ -51286,6 +51334,12 @@ "svuint32x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint32_t" }, @@ -51300,6 +51354,12 @@ "svuint64x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint64_t" }, @@ -51314,6 +51374,12 @@ "svuint8x2_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint8_t" }, @@ -51328,6 +51394,12 @@ "svfloat16x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svfloat16_t" }, @@ -51342,6 +51414,12 @@ "svfloat32x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svfloat32_t" }, @@ -51356,6 +51434,12 @@ "svfloat64x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svfloat64_t" }, @@ -51370,6 +51454,12 @@ "svint16x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint16_t" }, @@ -51384,6 +51474,12 @@ "svint32x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint32_t" }, @@ -51398,6 +51494,12 @@ "svint64x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint64_t" }, @@ -51412,6 +51514,12 @@ "svint8x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint8_t" }, @@ -51426,6 +51534,12 @@ "svuint16x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint16_t" }, @@ -51440,6 +51554,12 @@ "svuint32x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint32_t" }, @@ -51454,6 +51574,12 @@ "svuint64x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint64_t" }, @@ -51468,6 +51594,12 @@ "svuint8x3_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint8_t" }, @@ -51482,6 +51614,12 @@ "svfloat16x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svfloat16_t" }, @@ -51496,6 +51634,12 @@ "svfloat32x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svfloat32_t" }, @@ -51510,6 +51654,12 @@ "svfloat64x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svfloat64_t" }, @@ -51524,6 +51674,12 @@ "svint16x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint16_t" }, @@ -51538,6 +51694,12 @@ "svint32x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint32_t" }, @@ -51552,6 +51714,12 @@ "svint64x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint64_t" }, @@ -51566,6 +51734,12 @@ "svint8x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint8_t" }, @@ -51580,6 +51754,12 @@ "svuint16x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint16_t" }, @@ -51594,6 +51774,12 @@ "svuint32x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint32_t" }, @@ -51608,6 +51794,12 @@ "svuint64x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint64_t" }, @@ -51622,6 +51814,12 @@ "svuint8x4_t tuple", "uint64_t imm_index" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint8_t" }, From 992cb1d9de25ea8181dc2ea2403b91d6306f4868 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 1 Jun 2026 12:44:41 +0000 Subject: [PATCH 12/77] arm-intrinsics: `svset{2,3,4}` These intrinsics need `Arguments_Preparation` added so that the intrinsic-test tool knows to generate const arguments. --- .../intrinsics_data/arm_intrinsics.json | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/library/stdarch/intrinsics_data/arm_intrinsics.json b/library/stdarch/intrinsics_data/arm_intrinsics.json index 582de29741587..7f749fe4d8842 100644 --- a/library/stdarch/intrinsics_data/arm_intrinsics.json +++ b/library/stdarch/intrinsics_data/arm_intrinsics.json @@ -163197,6 +163197,12 @@ "uint64_t imm_index", "svfloat16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svfloat16x2_t" }, @@ -163212,6 +163218,12 @@ "uint64_t imm_index", "svfloat32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svfloat32x2_t" }, @@ -163227,6 +163239,12 @@ "uint64_t imm_index", "svfloat64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svfloat64x2_t" }, @@ -163242,6 +163260,12 @@ "uint64_t imm_index", "svint16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint16x2_t" }, @@ -163257,6 +163281,12 @@ "uint64_t imm_index", "svint32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint32x2_t" }, @@ -163272,6 +163302,12 @@ "uint64_t imm_index", "svint64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint64x2_t" }, @@ -163287,6 +163323,12 @@ "uint64_t imm_index", "svint8_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svint8x2_t" }, @@ -163302,6 +163344,12 @@ "uint64_t imm_index", "svuint16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint16x2_t" }, @@ -163317,6 +163365,12 @@ "uint64_t imm_index", "svuint32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint32x2_t" }, @@ -163332,6 +163386,12 @@ "uint64_t imm_index", "svuint64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint64x2_t" }, @@ -163347,6 +163407,12 @@ "uint64_t imm_index", "svuint8_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 1 + } + }, "return_type": { "value": "svuint8x2_t" }, @@ -163362,6 +163428,12 @@ "uint64_t imm_index", "svfloat16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svfloat16x3_t" }, @@ -163377,6 +163449,12 @@ "uint64_t imm_index", "svfloat32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svfloat32x3_t" }, @@ -163392,6 +163470,12 @@ "uint64_t imm_index", "svfloat64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svfloat64x3_t" }, @@ -163407,6 +163491,12 @@ "uint64_t imm_index", "svint16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint16x3_t" }, @@ -163422,6 +163512,12 @@ "uint64_t imm_index", "svint32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint32x3_t" }, @@ -163437,6 +163533,12 @@ "uint64_t imm_index", "svint64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint64x3_t" }, @@ -163452,6 +163554,12 @@ "uint64_t imm_index", "svint8_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svint8x3_t" }, @@ -163467,6 +163575,12 @@ "uint64_t imm_index", "svuint16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint16x3_t" }, @@ -163482,6 +163596,12 @@ "uint64_t imm_index", "svuint32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint32x3_t" }, @@ -163497,6 +163617,12 @@ "uint64_t imm_index", "svuint64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint64x3_t" }, @@ -163512,6 +163638,12 @@ "uint64_t imm_index", "svuint8_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 2 + } + }, "return_type": { "value": "svuint8x3_t" }, @@ -163527,6 +163659,12 @@ "uint64_t imm_index", "svfloat16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svfloat16x4_t" }, @@ -163542,6 +163680,12 @@ "uint64_t imm_index", "svfloat32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svfloat32x4_t" }, @@ -163557,6 +163701,12 @@ "uint64_t imm_index", "svfloat64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svfloat64x4_t" }, @@ -163572,6 +163722,12 @@ "uint64_t imm_index", "svint16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint16x4_t" }, @@ -163587,6 +163743,12 @@ "uint64_t imm_index", "svint32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint32x4_t" }, @@ -163602,6 +163764,12 @@ "uint64_t imm_index", "svint64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint64x4_t" }, @@ -163617,6 +163785,12 @@ "uint64_t imm_index", "svint8_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svint8x4_t" }, @@ -163632,6 +163806,12 @@ "uint64_t imm_index", "svuint16_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint16x4_t" }, @@ -163647,6 +163827,12 @@ "uint64_t imm_index", "svuint32_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint32x4_t" }, @@ -163662,6 +163848,12 @@ "uint64_t imm_index", "svuint64_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint64x4_t" }, @@ -163677,6 +163869,12 @@ "uint64_t imm_index", "svuint8_t x" ], + "Arguments_Preparation": { + "imm_index": { + "minimum": 0, + "maximum": 3 + } + }, "return_type": { "value": "svuint8x4_t" }, From 35e9bf6555e4d45a982e82c7eb67fa62b7713fa4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 13/77] core_arch: redefine `svrev_b{16,32,64}` Clang uses the `llvm.aarch64.sve.rev.bN` intrinsic for `svrev` with `b16`, `b32` and `b64`. This required small generator changes so it knew a bool-to-bool conversion was a no-op and a new blanket identity impl of `SveInto` so the calls generated compile. --- .../core_arch/src/aarch64/sve/generated.rs | 44 +++++++++---------- .../crates/core_arch/src/aarch64/sve/mod.rs | 8 ++++ .../stdarch-gen-arm/spec/sve/aarch64.spec.yml | 9 ++-- .../crates/stdarch-gen-arm/src/intrinsic.rs | 1 + 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs index 116adcf746802..42d2d1c5b899b 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs @@ -35226,19 +35226,6 @@ pub fn svreinterpret_u64_u64(op: svuint64_t) -> svuint64_t { unsafe { crate::intrinsics::transmute_unchecked(op) } } #[doc = "Reverse all elements"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrev_b8)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(rev))] -pub fn svrev_b8(op: svbool_t) -> svbool_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.vector.reverse.nxv16i1")] - fn _svrev_b8(op: svbool_t) -> svbool_t; - } - unsafe { _svrev_b8(op) } -} -#[doc = "Reverse all elements"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrev_b16)"] #[inline] #[target_feature(enable = "sve")] @@ -35246,10 +35233,10 @@ pub fn svrev_b8(op: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(rev))] pub fn svrev_b16(op: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.vector.reverse.nxv8i1")] - fn _svrev_b16(op: svbool8_t) -> svbool8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.rev.b16")] + fn _svrev_b16(op: svbool_t) -> svbool_t; } - unsafe { _svrev_b16(op.sve_into()).sve_into() } + unsafe { _svrev_b16(op.sve_into()) } } #[doc = "Reverse all elements"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrev_b32)"] @@ -35259,10 +35246,10 @@ pub fn svrev_b16(op: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(rev))] pub fn svrev_b32(op: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.vector.reverse.nxv4i1")] - fn _svrev_b32(op: svbool4_t) -> svbool4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.rev.b32")] + fn _svrev_b32(op: svbool_t) -> svbool_t; } - unsafe { _svrev_b32(op.sve_into()).sve_into() } + unsafe { _svrev_b32(op.sve_into()) } } #[doc = "Reverse all elements"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrev_b64)"] @@ -35272,10 +35259,10 @@ pub fn svrev_b32(op: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(rev))] pub fn svrev_b64(op: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.vector.reverse.nxv2i1")] - fn _svrev_b64(op: svbool2_t) -> svbool2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.rev.b64")] + fn _svrev_b64(op: svbool_t) -> svbool_t; } - unsafe { _svrev_b64(op.sve_into()).sve_into() } + unsafe { _svrev_b64(op.sve_into()) } } #[doc = "Reverse all elements"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrev[_f32])"] @@ -35391,6 +35378,19 @@ pub fn svrev_u32(op: svuint32_t) -> svuint32_t { pub fn svrev_u64(op: svuint64_t) -> svuint64_t { unsafe { svrev_s64(op.as_signed()).as_unsigned() } } +#[doc = "Reverse all elements"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrev[_b8])"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(rev))] +pub fn svrev_b8(op: svbool_t) -> svbool_t { + unsafe extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.vector.reverse.nxv16i1")] + fn _svrev_b8(op: svbool_t) -> svbool_t; + } + unsafe { _svrev_b8(op) } +} #[doc = "Reverse bytes within elements"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svrevb[_s16]_m)"] #[inline] diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs index c6d5d57aca869..f11ca660b15e2 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs @@ -28,6 +28,14 @@ pub(super) trait SveInto: Sized { unsafe fn sve_into(self) -> T; } +impl SveInto for T { + #[inline] + #[target_feature(enable = "sve")] + unsafe fn sve_into(self) -> T { + self + } +} + macro_rules! impl_sve_type { ($(($v:vis, $elem_type:ty, $name:ident, $elt:literal))*) => ($( #[doc = concat!("Scalable vector of type ", stringify!($elem_type))] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml index 1f65732412241..057491d31c4e9 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml @@ -1207,7 +1207,7 @@ intrinsics: doc: Reverse all elements arguments: ["op: {sve_type}"] return_type: "{sve_type}" - types: [f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] + types: [b8, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] assert_instr: [rev] compose: - LLVMLink: { name: "llvm.vector.reverse.{sve_type}" } @@ -1217,10 +1217,13 @@ intrinsics: doc: Reverse all elements arguments: ["op: {sve_type}"] return_type: "{sve_type}" - types: [b8, b16, b32, b64] + types: [b16, b32, b64] assert_instr: [rev] compose: - - LLVMLink: { name: "llvm.vector.reverse.{sve_type}" } + - LLVMLink: + name: "llvm.aarch64.sve.rev.b{size}" + arguments: ["op: svbool_t"] + return_type: "svbool_t" - name: svrevb[_{type}]{_mxz} attr: [*sve-unstable] diff --git a/library/stdarch/crates/stdarch-gen-arm/src/intrinsic.rs b/library/stdarch/crates/stdarch-gen-arm/src/intrinsic.rs index 72fb97fee1f08..f96f05dfec680 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/intrinsic.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/intrinsic.rs @@ -1604,6 +1604,7 @@ impl Intrinsic { (Some(BaseTypeKind::Float), Some(BaseTypeKind::Float)) => ex, (Some(BaseTypeKind::UInt), Some(BaseTypeKind::UInt)) => ex, (Some(BaseTypeKind::Poly), Some(BaseTypeKind::Poly)) => ex, + (Some(BaseTypeKind::Bool), Some(BaseTypeKind::Bool)) => ex, (None, None) => ex, _ => unreachable!( From 6346107492ea71d30f52d7ce5294c6e7f8c73dbf Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 14/77] core_arch: redefine `sv{zip,uzp}_b{16,32,64}` Clang uses the `llvm.aarch64.sve.zip.bN` intrinsic for `svzip` with `b16`, `b32` and `b64` and the `llvm.aarch64.sve.uzp.bN` intrinsic for `svuzp` with the same types. --- .../core_arch/src/aarch64/sve/generated.rs | 176 +++++++++--------- .../stdarch-gen-arm/spec/sve/aarch64.spec.yml | 36 ++-- 2 files changed, 112 insertions(+), 100 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs index 42d2d1c5b899b..ac3070918a025 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs @@ -43336,19 +43336,6 @@ pub fn svusmmla_s32(op1: svint32_t, op2: svuint8_t, op3: svint8_t) -> svint32_t unsafe { _svusmmla_s32(op1, op2.as_signed(), op3) } } #[doc = "Concatenate even elements from two inputs"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1_b8)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(uzp1))] -pub fn svuzp1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.nxv16i1")] - fn _svuzp1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; - } - unsafe { _svuzp1_b8(op1, op2) } -} -#[doc = "Concatenate even elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1_b16)"] #[inline] #[target_feature(enable = "sve")] @@ -43356,10 +43343,10 @@ pub fn svuzp1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(uzp1))] pub fn svuzp1_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.nxv8i1")] - fn _svuzp1_b16(op1: svbool8_t, op2: svbool8_t) -> svbool8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.b16")] + fn _svuzp1_b16(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svuzp1_b16(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svuzp1_b16(op1.sve_into(), op2.sve_into()) } } #[doc = "Concatenate even elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1_b32)"] @@ -43369,10 +43356,10 @@ pub fn svuzp1_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(uzp1))] pub fn svuzp1_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.nxv4i1")] - fn _svuzp1_b32(op1: svbool4_t, op2: svbool4_t) -> svbool4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.b32")] + fn _svuzp1_b32(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svuzp1_b32(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svuzp1_b32(op1.sve_into(), op2.sve_into()) } } #[doc = "Concatenate even elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1_b64)"] @@ -43382,10 +43369,10 @@ pub fn svuzp1_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(uzp1))] pub fn svuzp1_b64(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.nxv2i1")] - fn _svuzp1_b64(op1: svbool2_t, op2: svbool2_t) -> svbool2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.b64")] + fn _svuzp1_b64(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svuzp1_b64(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svuzp1_b64(op1.sve_into(), op2.sve_into()) } } #[doc = "Concatenate even elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1[_f32])"] @@ -43501,6 +43488,19 @@ pub fn svuzp1_u32(op1: svuint32_t, op2: svuint32_t) -> svuint32_t { pub fn svuzp1_u64(op1: svuint64_t, op2: svuint64_t) -> svuint64_t { unsafe { svuzp1_s64(op1.as_signed(), op2.as_signed()).as_unsigned() } } +#[doc = "Concatenate even elements from two inputs"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1[_b8])"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(uzp1))] +pub fn svuzp1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { + unsafe extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp1.nxv16i1")] + fn _svuzp1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; + } + unsafe { _svuzp1_b8(op1, op2) } +} #[doc = "Concatenate even quadwords from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp1q[_f32])"] #[inline] @@ -43616,19 +43616,6 @@ pub fn svuzp1q_u64(op1: svuint64_t, op2: svuint64_t) -> svuint64_t { unsafe { svuzp1q_s64(op1.as_signed(), op2.as_signed()).as_unsigned() } } #[doc = "Concatenate odd elements from two inputs"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2_b8)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(uzp2))] -pub fn svuzp2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.nxv16i1")] - fn _svuzp2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; - } - unsafe { _svuzp2_b8(op1, op2) } -} -#[doc = "Concatenate odd elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2_b16)"] #[inline] #[target_feature(enable = "sve")] @@ -43636,10 +43623,10 @@ pub fn svuzp2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(uzp2))] pub fn svuzp2_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.nxv8i1")] - fn _svuzp2_b16(op1: svbool8_t, op2: svbool8_t) -> svbool8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.b16")] + fn _svuzp2_b16(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svuzp2_b16(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svuzp2_b16(op1.sve_into(), op2.sve_into()) } } #[doc = "Concatenate odd elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2_b32)"] @@ -43649,10 +43636,10 @@ pub fn svuzp2_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(uzp2))] pub fn svuzp2_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.nxv4i1")] - fn _svuzp2_b32(op1: svbool4_t, op2: svbool4_t) -> svbool4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.b32")] + fn _svuzp2_b32(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svuzp2_b32(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svuzp2_b32(op1.sve_into(), op2.sve_into()) } } #[doc = "Concatenate odd elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2_b64)"] @@ -43662,10 +43649,10 @@ pub fn svuzp2_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(uzp2))] pub fn svuzp2_b64(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.nxv2i1")] - fn _svuzp2_b64(op1: svbool2_t, op2: svbool2_t) -> svbool2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.b64")] + fn _svuzp2_b64(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svuzp2_b64(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svuzp2_b64(op1.sve_into(), op2.sve_into()) } } #[doc = "Concatenate odd elements from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2[_f32])"] @@ -43781,6 +43768,19 @@ pub fn svuzp2_u32(op1: svuint32_t, op2: svuint32_t) -> svuint32_t { pub fn svuzp2_u64(op1: svuint64_t, op2: svuint64_t) -> svuint64_t { unsafe { svuzp2_s64(op1.as_signed(), op2.as_signed()).as_unsigned() } } +#[doc = "Concatenate odd elements from two inputs"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2[_b8])"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(uzp2))] +pub fn svuzp2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { + unsafe extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.uzp2.nxv16i1")] + fn _svuzp2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; + } + unsafe { _svuzp2_b8(op1, op2) } +} #[doc = "Concatenate odd quadwords from two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svuzp2q[_f32])"] #[inline] @@ -44421,19 +44421,6 @@ pub fn svwrffr(op: svbool_t) { unsafe { _svwrffr(op) } } #[doc = "Interleave elements from low halves of two inputs"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1_b8)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(zip1))] -pub fn svzip1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.nxv16i1")] - fn _svzip1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; - } - unsafe { _svzip1_b8(op1, op2) } -} -#[doc = "Interleave elements from low halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1_b16)"] #[inline] #[target_feature(enable = "sve")] @@ -44441,10 +44428,10 @@ pub fn svzip1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(zip1))] pub fn svzip1_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.nxv8i1")] - fn _svzip1_b16(op1: svbool8_t, op2: svbool8_t) -> svbool8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.b16")] + fn _svzip1_b16(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svzip1_b16(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svzip1_b16(op1.sve_into(), op2.sve_into()) } } #[doc = "Interleave elements from low halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1_b32)"] @@ -44454,10 +44441,10 @@ pub fn svzip1_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(zip1))] pub fn svzip1_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.nxv4i1")] - fn _svzip1_b32(op1: svbool4_t, op2: svbool4_t) -> svbool4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.b32")] + fn _svzip1_b32(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svzip1_b32(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svzip1_b32(op1.sve_into(), op2.sve_into()) } } #[doc = "Interleave elements from low halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1_b64)"] @@ -44467,10 +44454,10 @@ pub fn svzip1_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(zip1))] pub fn svzip1_b64(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.nxv2i1")] - fn _svzip1_b64(op1: svbool2_t, op2: svbool2_t) -> svbool2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.b64")] + fn _svzip1_b64(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svzip1_b64(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svzip1_b64(op1.sve_into(), op2.sve_into()) } } #[doc = "Interleave elements from low halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1[_f32])"] @@ -44586,6 +44573,19 @@ pub fn svzip1_u32(op1: svuint32_t, op2: svuint32_t) -> svuint32_t { pub fn svzip1_u64(op1: svuint64_t, op2: svuint64_t) -> svuint64_t { unsafe { svzip1_s64(op1.as_signed(), op2.as_signed()).as_unsigned() } } +#[doc = "Interleave elements from low halves of two inputs"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1[_b8])"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(zip1))] +pub fn svzip1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { + unsafe extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip1.nxv16i1")] + fn _svzip1_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; + } + unsafe { _svzip1_b8(op1, op2) } +} #[doc = "Interleave quadwords from low halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip1q[_f32])"] #[inline] @@ -44701,19 +44701,6 @@ pub fn svzip1q_u64(op1: svuint64_t, op2: svuint64_t) -> svuint64_t { unsafe { svzip1q_s64(op1.as_signed(), op2.as_signed()).as_unsigned() } } #[doc = "Interleave elements from high halves of two inputs"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2_b8)"] -#[inline] -#[target_feature(enable = "sve")] -#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] -#[cfg_attr(test, assert_instr(zip2))] -pub fn svzip2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { - unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.nxv16i1")] - fn _svzip2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; - } - unsafe { _svzip2_b8(op1, op2) } -} -#[doc = "Interleave elements from high halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2_b16)"] #[inline] #[target_feature(enable = "sve")] @@ -44721,10 +44708,10 @@ pub fn svzip2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(zip2))] pub fn svzip2_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.nxv8i1")] - fn _svzip2_b16(op1: svbool8_t, op2: svbool8_t) -> svbool8_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.b16")] + fn _svzip2_b16(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svzip2_b16(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svzip2_b16(op1.sve_into(), op2.sve_into()) } } #[doc = "Interleave elements from high halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2_b32)"] @@ -44734,10 +44721,10 @@ pub fn svzip2_b16(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(zip2))] pub fn svzip2_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.nxv4i1")] - fn _svzip2_b32(op1: svbool4_t, op2: svbool4_t) -> svbool4_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.b32")] + fn _svzip2_b32(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svzip2_b32(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svzip2_b32(op1.sve_into(), op2.sve_into()) } } #[doc = "Interleave elements from high halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2_b64)"] @@ -44747,10 +44734,10 @@ pub fn svzip2_b32(op1: svbool_t, op2: svbool_t) -> svbool_t { #[cfg_attr(test, assert_instr(zip2))] pub fn svzip2_b64(op1: svbool_t, op2: svbool_t) -> svbool_t { unsafe extern "unadjusted" { - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.nxv2i1")] - fn _svzip2_b64(op1: svbool2_t, op2: svbool2_t) -> svbool2_t; + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.b64")] + fn _svzip2_b64(op1: svbool_t, op2: svbool_t) -> svbool_t; } - unsafe { _svzip2_b64(op1.sve_into(), op2.sve_into()).sve_into() } + unsafe { _svzip2_b64(op1.sve_into(), op2.sve_into()) } } #[doc = "Interleave elements from high halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2[_f32])"] @@ -44866,6 +44853,19 @@ pub fn svzip2_u32(op1: svuint32_t, op2: svuint32_t) -> svuint32_t { pub fn svzip2_u64(op1: svuint64_t, op2: svuint64_t) -> svuint64_t { unsafe { svzip2_s64(op1.as_signed(), op2.as_signed()).as_unsigned() } } +#[doc = "Interleave elements from high halves of two inputs"] +#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2[_b8])"] +#[inline] +#[target_feature(enable = "sve")] +#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] +#[cfg_attr(test, assert_instr(zip2))] +pub fn svzip2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t { + unsafe extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.zip2.nxv16i1")] + fn _svzip2_b8(op1: svbool_t, op2: svbool_t) -> svbool_t; + } + unsafe { _svzip2_b8(op1, op2) } +} #[doc = "Interleave quadwords from high halves of two inputs"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svzip2q[_f32])"] #[inline] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml index 057491d31c4e9..138d5ba31175b 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/sve/aarch64.spec.yml @@ -1021,7 +1021,7 @@ intrinsics: doc: Interleave elements from low halves of two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] + types: [b8, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] assert_instr: [zip1] compose: - LLVMLink: { name: "zip1.{sve_type}" } @@ -1031,10 +1031,13 @@ intrinsics: doc: Interleave elements from low halves of two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [b8, b16, b32, b64] + types: [b16, b32, b64] assert_instr: [zip1] compose: - - LLVMLink: { name: "zip1.{sve_type}" } + - LLVMLink: + name: "llvm.aarch64.sve.zip1.b{size}" + arguments: ["op1: svbool_t", "op2: svbool_t"] + return_type: "svbool_t" - name: svzip1q[_{type}] attr: [*sve-unstable] @@ -1052,7 +1055,7 @@ intrinsics: doc: Interleave elements from high halves of two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] + types: [b8, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] assert_instr: [zip2] compose: - LLVMLink: { name: "zip2.{sve_type}" } @@ -1062,10 +1065,13 @@ intrinsics: doc: Interleave elements from high halves of two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [b8, b16, b32, b64] + types: [b16, b32, b64] assert_instr: [zip2] compose: - - LLVMLink: { name: "zip2.{sve_type}" } + - LLVMLink: + name: "llvm.aarch64.sve.zip2.b{size}" + arguments: ["op1: svbool_t", "op2: svbool_t"] + return_type: "svbool_t" - name: svzip2q[_{type}] attr: [*sve-unstable] @@ -1083,7 +1089,7 @@ intrinsics: doc: Concatenate even elements from two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] + types: [b8, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] assert_instr: [uzp1] compose: - LLVMLink: { name: "uzp1.{sve_type}" } @@ -1093,10 +1099,13 @@ intrinsics: doc: Concatenate even elements from two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [b8, b16, b32, b64] + types: [b16, b32, b64] assert_instr: [uzp1] compose: - - LLVMLink: { name: "uzp1.{sve_type}" } + - LLVMLink: + name: "llvm.aarch64.sve.uzp1.b{size}" + arguments: ["op1: svbool_t", "op2: svbool_t"] + return_type: "svbool_t" - name: svuzp1q[_{type}] attr: [*sve-unstable] @@ -1114,7 +1123,7 @@ intrinsics: doc: Concatenate odd elements from two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] + types: [b8, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64] assert_instr: [uzp2] compose: - LLVMLink: { name: "uzp2.{sve_type}" } @@ -1124,10 +1133,13 @@ intrinsics: doc: Concatenate odd elements from two inputs arguments: ["op1: {sve_type}", "op2: {sve_type}"] return_type: "{sve_type}" - types: [b8, b16, b32, b64] + types: [b16, b32, b64] assert_instr: [uzp2] compose: - - LLVMLink: { name: "uzp2.{sve_type}" } + - LLVMLink: + name: "llvm.aarch64.sve.uzp2.b{size}" + arguments: ["op1: svbool_t", "op2: svbool_t"] + return_type: "svbool_t" - name: svuzp2q[_{type}] attr: [*sve-unstable] From ae20f1014f7306269b046f7927f463c3500fa9d5 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 15/77] intrinsic-test: fwd args in `intrinsic-test.sh` Forward addl. arguments to `intrinsic-test.sh` to `cargo test` so that `--no-fail-fast` or a specific test name can be passed. --- library/stdarch/ci/intrinsic-test.sh | 31 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/library/stdarch/ci/intrinsic-test.sh b/library/stdarch/ci/intrinsic-test.sh index 0441611f38fd2..8de7a4cfa5221 100755 --- a/library/stdarch/ci/intrinsic-test.sh +++ b/library/stdarch/ci/intrinsic-test.sh @@ -1,13 +1,19 @@ #!/usr/bin/env sh -set -ex - if [ $# -lt 2 ]; then - >&2 echo "Usage: $0 " + >&2 echo "Usage: $0 <..args for \`cargo test\`..>" exit 1 fi -case ${2} in +set -ex + +# Pop both arguments and leave "$@" as containing args to be forwarded to `cargo test` +TARGET="$1" +shift +CC_KIND="$1" +shift + +case ${CC_KIND} in clang) export CC="${CLANG_PATH}" CC_ARG_STYLE=clang @@ -22,7 +28,7 @@ case ${2} in CC_ARG_STYLE=clang ;; *) - >&2 echo "Unknown compiler: ${2}" + >&2 echo "Unknown compiler: ${CC_KIND}" exit 1 ;; esac @@ -35,7 +41,7 @@ echo "PROFILE=${PROFILE}" INTRINSIC_TEST="--manifest-path=crates/intrinsic-test/Cargo.toml" -case ${1} in +case ${TARGET} in aarch64_be*) export CFLAGS="-I${AARCH64_BE_TOOLCHAIN}/aarch64_be-none-linux-gnu/libc/usr/include --sysroot={AARCH64_BE_TOOLCHAIN}/aarch64_be-none-linux-gnu/libc -Wno-nonportable-vector-initialization" ARCH=aarch64_be @@ -60,24 +66,25 @@ case ${1} in esac -case "${1}" in +case "${TARGET}" in x86_64-unknown-linux-gnu*) env -u CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER \ cargo run "${INTRINSIC_TEST}" --release \ --bin intrinsic-test -- intrinsics_data/x86-intel.xml \ --skip "crates/intrinsic-test/missing_${ARCH}_common.txt" \ - --skip "crates/intrinsic-test/missing_${ARCH}_${2}.txt" \ - --target "${1}" \ + --skip "crates/intrinsic-test/missing_${ARCH}_${CC_KIND}.txt" \ + --target "${TARGET}" \ --cc-arg-style "${CC_ARG_STYLE}" ;; *) cargo run "${INTRINSIC_TEST}" --release \ --bin intrinsic-test -- intrinsics_data/arm_intrinsics.json \ --skip "crates/intrinsic-test/missing_${ARCH}_common.txt" \ - --skip "crates/intrinsic-test/missing_${ARCH}_${2}.txt" \ - --target "${1}" \ + --skip "crates/intrinsic-test/missing_${ARCH}_${CC_KIND}.txt" \ + --target "${TARGET}" \ --cc-arg-style "${CC_ARG_STYLE}" ;; esac -cargo test --manifest-path=rust_programs/Cargo.toml --target "${1}" --profile "${PROFILE}" --tests +cargo test --manifest-path=rust_programs/Cargo.toml --target "${TARGET}" --profile "${PROFILE}" \ + --tests "$@" From e668e1be8439fbe641e716261c4780926c84a519 Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Mon, 8 Jun 2026 15:05:46 +0100 Subject: [PATCH 16/77] move drop and dropck tests out of tests/ui/issues --- .../drop-with-trait-bound-calls-method-on-self.rs} | 0 .../drop-impl-for-type-param-with-trait-bound.rs} | 0 .../drop-impl-for-type-param-with-trait-bound.stderr} | 0 .../dropck-resolves-associated-type-in-field.rs} | 0 .../self-referential-struct-with-boxed-closure.rs} | 0 .../method-with-self-trait-bound-not-dyn-safe.rs} | 0 .../method-with-self-trait-bound-not-dyn-safe.stderr} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-4252.rs => drop/drop-with-trait-bound-calls-method-on-self.rs} (100%) rename tests/ui/{issues/issue-41974.rs => dropck/drop-impl-for-type-param-with-trait-bound.rs} (100%) rename tests/ui/{issues/issue-41974.stderr => dropck/drop-impl-for-type-param-with-trait-bound.stderr} (100%) rename tests/ui/{issues/issue-48132.rs => dropck/dropck-resolves-associated-type-in-field.rs} (100%) rename tests/ui/{issues/issue-26641.rs => dropck/self-referential-struct-with-boxed-closure.rs} (100%) rename tests/ui/{issues/issue-50781.rs => dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs} (100%) rename tests/ui/{issues/issue-50781.stderr => dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr} (100%) diff --git a/tests/ui/issues/issue-4252.rs b/tests/ui/drop/drop-with-trait-bound-calls-method-on-self.rs similarity index 100% rename from tests/ui/issues/issue-4252.rs rename to tests/ui/drop/drop-with-trait-bound-calls-method-on-self.rs diff --git a/tests/ui/issues/issue-41974.rs b/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.rs similarity index 100% rename from tests/ui/issues/issue-41974.rs rename to tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.rs diff --git a/tests/ui/issues/issue-41974.stderr b/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.stderr similarity index 100% rename from tests/ui/issues/issue-41974.stderr rename to tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.stderr diff --git a/tests/ui/issues/issue-48132.rs b/tests/ui/dropck/dropck-resolves-associated-type-in-field.rs similarity index 100% rename from tests/ui/issues/issue-48132.rs rename to tests/ui/dropck/dropck-resolves-associated-type-in-field.rs diff --git a/tests/ui/issues/issue-26641.rs b/tests/ui/dropck/self-referential-struct-with-boxed-closure.rs similarity index 100% rename from tests/ui/issues/issue-26641.rs rename to tests/ui/dropck/self-referential-struct-with-boxed-closure.rs diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs similarity index 100% rename from tests/ui/issues/issue-50781.rs rename to tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr similarity index 100% rename from tests/ui/issues/issue-50781.stderr rename to tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr From 2e4d8c9d49679f71d56d9e60f36e26b9acfc1534 Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Mon, 8 Jun 2026 15:32:52 +0100 Subject: [PATCH 17/77] add issue links and bless --- .../ui/drop/drop-with-trait-bound-calls-method-on-self.rs | 1 + .../dropck/drop-impl-for-type-param-with-trait-bound.rs | 1 + .../drop-impl-for-type-param-with-trait-bound.stderr | 4 ++-- .../ui/dropck/dropck-resolves-associated-type-in-field.rs | 1 + .../dropck/self-referential-struct-with-boxed-closure.rs | 1 + .../method-with-self-trait-bound-not-dyn-safe.rs | 1 + .../method-with-self-trait-bound-not-dyn-safe.stderr | 8 ++++---- 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/ui/drop/drop-with-trait-bound-calls-method-on-self.rs b/tests/ui/drop/drop-with-trait-bound-calls-method-on-self.rs index 1939ad15f143a..7032a6bc5e759 100644 --- a/tests/ui/drop/drop-with-trait-bound-calls-method-on-self.rs +++ b/tests/ui/drop/drop-with-trait-bound-calls-method-on-self.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/4252 //@ run-pass trait X { fn call(&self, x: &T); diff --git a/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.rs b/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.rs index 10c363479a374..9e046dee42cf7 100644 --- a/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.rs +++ b/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/41974 #[derive(Copy, Clone)] struct Flags; diff --git a/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.stderr b/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.stderr index 2ae073dd1ba82..cc3488aaca0cf 100644 --- a/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.stderr +++ b/tests/ui/dropck/drop-impl-for-type-param-with-trait-bound.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct`) - --> $DIR/issue-41974.rs:7:6 + --> $DIR/drop-impl-for-type-param-with-trait-bound.rs:8:6 | LL | impl Drop for T where T: A { | ^ uncovered type parameter @@ -8,7 +8,7 @@ LL | impl Drop for T where T: A { = note: only traits defined in the current crate can be implemented for a type parameter error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions - --> $DIR/issue-41974.rs:7:18 + --> $DIR/drop-impl-for-type-param-with-trait-bound.rs:8:18 | LL | impl Drop for T where T: A { | ^ must be a struct, enum, or union in the current crate diff --git a/tests/ui/dropck/dropck-resolves-associated-type-in-field.rs b/tests/ui/dropck/dropck-resolves-associated-type-in-field.rs index d8d7167a4ce82..16a44cd0d6de4 100644 --- a/tests/ui/dropck/dropck-resolves-associated-type-in-field.rs +++ b/tests/ui/dropck/dropck-resolves-associated-type-in-field.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/48132 // Regression test for #48132. This was failing due to problems around // the projection caching and dropck type enumeration. diff --git a/tests/ui/dropck/self-referential-struct-with-boxed-closure.rs b/tests/ui/dropck/self-referential-struct-with-boxed-closure.rs index 983bcbea92731..f78f3907de9a2 100644 --- a/tests/ui/dropck/self-referential-struct-with-boxed-closure.rs +++ b/tests/ui/dropck/self-referential-struct-with-boxed-closure.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/26641 //@ run-pass struct Parser<'a>(#[allow(dead_code)] Box); diff --git a/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs b/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs index d837b848591f2..39eee9129e1dd 100644 --- a/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs +++ b/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.rs @@ -1,3 +1,4 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/50781 trait Trait {} trait X { diff --git a/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr b/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr index 4ba3166b6c581..81f031a2123fd 100644 --- a/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr +++ b/tests/ui/dyn-compatibility/method-with-self-trait-bound-not-dyn-safe.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `X` is not dyn compatible - --> $DIR/issue-50781.rs:11:16 + --> $DIR/method-with-self-trait-bound-not-dyn-safe.rs:12:16 | LL | impl Trait for dyn X {} | ^^^^^ `X` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/issue-50781.rs:4:8 + --> $DIR/method-with-self-trait-bound-not-dyn-safe.rs:5:8 | LL | trait X { | - this trait is not dyn compatible... @@ -16,14 +16,14 @@ LL | fn foo(&self) where Self: Trait; = help: only type `()` implements `X`; consider using it directly instead. error[E0038]: the trait `X` is not dyn compatible - --> $DIR/issue-50781.rs:16:10 + --> $DIR/method-with-self-trait-bound-not-dyn-safe.rs:17:10 | LL | ::foo(&()); | ^ `X` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/issue-50781.rs:4:8 + --> $DIR/method-with-self-trait-bound-not-dyn-safe.rs:5:8 | LL | trait X { | - this trait is not dyn compatible... From 6a534731ff042bbca3cdcb858cc5e7f6bae9e327 Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 18 Jun 2026 12:20:35 +0200 Subject: [PATCH 18/77] add minimal NetBSD support --- src/tools/miri/ci/ci.sh | 1 + src/tools/miri/src/shims/unix/sync.rs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index f7c0b739c1dd4..42107adfe566a 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -168,6 +168,7 @@ case $HOST_TARGET in MANY_SEEDS=16 TEST_TARGET=x86_64-unknown-freebsd run_tests MANY_SEEDS=16 TEST_TARGET=i686-unknown-freebsd run_tests MANY_SEEDS=16 TEST_TARGET=x86_64-unknown-illumos run_tests + MANY_SEEDS=16 TEST_TARGET=x86_64-unknown-netbsd run_tests_minimal hello ;; armv7-unknown-linux-gnueabihf) # Host diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 4e351c1571218..a34314f3fbea6 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -35,7 +35,13 @@ const PTHREAD_INIT: u8 = 1; #[inline] fn mutexattr_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { interp_ok(match &ecx.tcx.sess.target.os { - Os::Linux | Os::Illumos | Os::Solaris | Os::MacOs | Os::FreeBsd | Os::Android => 0, + Os::Linux + | Os::Illumos + | Os::Solaris + | Os::MacOs + | Os::FreeBsd + | Os::Android + | Os::NetBsd => 0, os => throw_unsup_format!("`pthread_mutexattr` is not supported on {os}"), }) } @@ -135,8 +141,8 @@ impl SyncObj for PthreadMutex { fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &ecx.tcx.sess.target.os { Os::Linux | Os::Illumos | Os::Solaris | Os::FreeBsd | Os::Android => 0, - // macOS stores a signature in the first bytes, so we move to offset 4. - Os::MacOs => 4, + // macOS and NetBSD store a signature in the first bytes, so we move to offset 4. + Os::MacOs | Os::NetBsd => 4, os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), }; let offset = Size::from_bytes(offset); @@ -163,7 +169,7 @@ fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> check_static_initializer("PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP"); check_static_initializer("PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP"); } - Os::Illumos | Os::Solaris | Os::MacOs | Os::FreeBsd | Os::Android => { + Os::Illumos | Os::Solaris | Os::MacOs | Os::FreeBsd | Os::Android | Os::NetBsd => { // No non-standard initializers. } os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), From 9f27f6db2c9048a6ff9d24b3a0090f3d0bfd879e Mon Sep 17 00:00:00 2001 From: Mohamed Ali Date: Wed, 17 Jun 2026 14:53:50 +0300 Subject: [PATCH 19/77] [Priroda] Add structured locals output --- src/tools/miri/priroda/src/main.rs | 69 ++++++++++++++++--- .../tests/ui/locals_in_function.stdout | 8 ++- 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/priroda/src/main.rs b/src/tools/miri/priroda/src/main.rs index 2739b041b0b48..7ce46224a83e0 100644 --- a/src/tools/miri/priroda/src/main.rs +++ b/src/tools/miri/priroda/src/main.rs @@ -6,6 +6,7 @@ extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_hir; extern crate rustc_hir_analysis; +extern crate rustc_index; extern crate rustc_interface; extern crate rustc_log; extern crate rustc_middle; @@ -19,13 +20,15 @@ use std::path::PathBuf; use miri::*; use rustc_driver::Compilation; use rustc_hir::attrs::CrateType; +use rustc_index::IndexVec; use rustc_interface::interface; use rustc_middle::mir; +use rustc_middle::mir::{Local, VarDebugInfoContents}; use rustc_middle::ty::TyCtxt; use rustc_session::EarlyDiagCtxt; use rustc_session::config::ErrorOutputType; -use rustc_span::Span; use rustc_span::source_map::SourceMap; +use rustc_span::{Span, Symbol}; fn find_sysroot() -> String { std::env::var("MIRI_SYSROOT") @@ -129,6 +132,10 @@ struct PrirodaContext<'tcx> { last_location: Option, } +struct LocalDesc { + name: Option, + local: Local, +} /// Controls when execution returns to the frontend. enum ResumeMode { /// Stop at the next visible MIR instruction. @@ -336,15 +343,47 @@ impl<'tcx> PrirodaContext<'tcx> { } } - /// Returns the names of all user-visible locals in the innermost stack frame. + /// Returns structured descriptions for locals in the innermost stack frame. /// - /// Uses `var_debug_info` from the MIR body, which is the same source that - /// DWARF debug info is built from, so the names match what the user wrote. - fn list_locals(&self) -> Vec { + /// Starts from all MIR locals, then enriches them with source names from + /// `var_debug_info` when a debug entry maps directly to a whole local. + fn list_locals(&self) -> Vec { let Some(frame) = self.ecx.active_thread_stack().last() else { return Vec::new(); }; - frame.body().var_debug_info.iter().map(|info| info.name.to_string()).collect() + + self.local_desc_map(frame).into_iter().collect() + } + + fn local_desc_map( + &self, + frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>, + ) -> IndexVec { + // Initialize one description per MIR local so the table can be indexed by Local. + let mut locals: IndexVec = frame + .body() + .local_decls + .iter_enumerated() + .map(|(id, _local_decl)| LocalDesc { name: None, local: id }) + .collect(); + + // FIXME: Some debug-info entries do not have a backing MIR local, for example + // because the source variable was optimized out or is represented as a + // projection. This local-indexed table cannot represent those entries yet; + // the final locals list should become a `Vec` with `id : Option`, `id` + // could be renamed to `local`. + + // Attach source names from debug info when the debug entry maps directly to a whole MIR local. + for var_debug_info in &frame.body().var_debug_info { + if let VarDebugInfoContents::Place(place) = var_debug_info.value + && let Some(local) = place.as_local() + && locals[local].name.is_none() + { + locals[local].name = Some(var_debug_info.name); + } + } + + locals } } @@ -366,7 +405,7 @@ enum BreakpointSetResult { enum CommandResult { ExecutionStopped(StepResult), BreakpointResult(BreakpointSetResult), - Locals(Vec), + Locals(Vec), // FIXME: distinguish terminating the debugger session from disconnecting a // frontend and terminating the interpreted program once multiple frontends exist. TerminateSession, @@ -403,12 +442,20 @@ impl Cli { BreakpointSetResult::Duplicate => println!("Duplicate breakpoint"), }, - CommandResult::Locals(names) => - if names.is_empty() { + CommandResult::Locals(locals_desc) => + if locals_desc.is_empty() { println!("no locals"); } else { - for name in &names { - println!("{name}"); + for local_desc in &locals_desc { + let mut name_str = "None".to_string(); + if let Some(name) = local_desc.name { + name_str = name.to_string(); + } + println!( + "Name: {}, Id: _{}", + name_str, + local_desc.local.index(), + ); } }, CommandResult::TerminateSession => { diff --git a/src/tools/miri/priroda/tests/ui/locals_in_function.stdout b/src/tools/miri/priroda/tests/ui/locals_in_function.stdout index ed5889f5836e7..b6ecc17bc56b3 100644 --- a/src/tools/miri/priroda/tests/ui/locals_in_function.stdout +++ b/src/tools/miri/priroda/tests/ui/locals_in_function.stdout @@ -1,6 +1,10 @@ (priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/locals_in_function.rs:5 (priroda) Hit breakpoint {MANIFEST_DIR}/tests/ui/locals_in_function.rs:5 -(priroda) x -y +(priroda) Name: None, Id: _0 +Name: x, Id: _1 +Name: y, Id: _2 +Name: None, Id: _3 +Name: None, Id: _4 +Name: None, Id: _5 (priroda) quitting From e4181278f7bf63ede026af3538dc7aa02565b64a Mon Sep 17 00:00:00 2001 From: Mohamed Ali Date: Fri, 19 Jun 2026 12:42:23 +0300 Subject: [PATCH 20/77] [Priroda] Add type strings to locals output --- src/tools/miri/priroda/src/main.rs | 8 ++++++-- .../miri/priroda/tests/ui/locals_in_function.stdout | 12 ++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/tools/miri/priroda/src/main.rs b/src/tools/miri/priroda/src/main.rs index 7ce46224a83e0..fe67b21d2c134 100644 --- a/src/tools/miri/priroda/src/main.rs +++ b/src/tools/miri/priroda/src/main.rs @@ -135,6 +135,7 @@ struct PrirodaContext<'tcx> { struct LocalDesc { name: Option, local: Local, + ty: String, } /// Controls when execution returns to the frontend. enum ResumeMode { @@ -364,7 +365,9 @@ impl<'tcx> PrirodaContext<'tcx> { .body() .local_decls .iter_enumerated() - .map(|(id, _local_decl)| LocalDesc { name: None, local: id }) + .map(|(id, local_decl)| { + LocalDesc { name: None, local: id, ty: local_decl.ty.to_string() } + }) .collect(); // FIXME: Some debug-info entries do not have a backing MIR local, for example @@ -452,9 +455,10 @@ impl Cli { name_str = name.to_string(); } println!( - "Name: {}, Id: _{}", + "Name: {}, Id: _{}, Ty: {}", name_str, local_desc.local.index(), + local_desc.ty, ); } }, diff --git a/src/tools/miri/priroda/tests/ui/locals_in_function.stdout b/src/tools/miri/priroda/tests/ui/locals_in_function.stdout index b6ecc17bc56b3..4f2786d3e17b7 100644 --- a/src/tools/miri/priroda/tests/ui/locals_in_function.stdout +++ b/src/tools/miri/priroda/tests/ui/locals_in_function.stdout @@ -1,10 +1,10 @@ (priroda) breakpoint added: {MANIFEST_DIR}/tests/ui/locals_in_function.rs:5 (priroda) Hit breakpoint {MANIFEST_DIR}/tests/ui/locals_in_function.rs:5 -(priroda) Name: None, Id: _0 -Name: x, Id: _1 -Name: y, Id: _2 -Name: None, Id: _3 -Name: None, Id: _4 -Name: None, Id: _5 +(priroda) Name: None, Id: _0, Ty: () +Name: x, Id: _1, Ty: i32 +Name: y, Id: _2, Ty: bool +Name: None, Id: _3, Ty: (i32, bool) +Name: None, Id: _4, Ty: i32 +Name: None, Id: _5, Ty: bool (priroda) quitting From 37df0fcaf8206eeb873f3f47f8ed350e6232c185 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Fri, 19 Jun 2026 09:53:18 +0000 Subject: [PATCH 21/77] Prepare for merging from rust-lang/rust This updates the rust-version file to 8e150217bafcaaaa0c45bf685c55fd56cec48598. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 387bd8edd2196..e8cec4e0ee9c9 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -029c9e18dd1f4668e1d42bb187c1c263dfe20093 +8e150217bafcaaaa0c45bf685c55fd56cec48598 From 169a8e9e5954ec6759d611260330fbfd67098f9b Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 1 Jun 2026 12:44:41 +0000 Subject: [PATCH 22/77] intrinsic-test: skip unimplemented SVE intrinsics Various SVE intrinsics are not yet implemented in stdarch, but are present in the `arm_intrinsics.json` and so should be skipped. --- .../crates/intrinsic-test/src/arm/mod.rs | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 378f23ba7c361..9f75e301ace2e 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -6,7 +6,7 @@ mod types; use crate::common::SupportedArchitectureTest; use crate::common::cli::{CcArgStyle, ProcessedCli}; use crate::common::intrinsic::Intrinsic; -use crate::common::intrinsic_helpers::TypeKind; +use crate::common::intrinsic_helpers::{SimdLen, TypeKind}; use intrinsic::ArmIntrinsicType; use json_parser::get_neon_intrinsics; @@ -54,6 +54,42 @@ impl SupportedArchitectureTest for ArmArchitectureTest { // Skip bfloat intrinsics - not currently supported .filter(|i| i.results.kind() != TypeKind::BFloat) .filter(|i| !i.arguments.iter().any(|a| a.ty.kind() == TypeKind::BFloat)) + // Skip SVE intrinsics that have `f16` - not yet implemented! + .filter(|i| { + let has_f16_arg = i + .arguments + .iter() + .any(|a| a.ty.kind() == TypeKind::Float && a.ty.bit_len == Some(16)); + let has_sve_arg = i + .arguments + .iter() + .any(|a| a.ty.simd_len == Some(SimdLen::Scalable)); + !(has_f16_arg && has_sve_arg) + }) + .filter(|i| { + let has_f16_ret = + i.results.kind() == TypeKind::Float && i.results.bit_len == Some(16); + let has_sve_ret = i.results.simd_len == Some(SimdLen::Scalable); + !(has_f16_ret && has_sve_ret) + }) + // Skip `svqcvtn{u,}n*_x2` intrinsics - not yet implemented! + .filter(|i| !(i.name.starts_with("svqcvtn") && i.name.ends_with("_x2"))) + // Skip `svqrshr{u,}n*_x2` intrinsics - not yet implemented! + .filter(|i| !(i.name.starts_with("svqrshrn") && i.name.ends_with("_x2"))) + .filter(|i| !(i.name.starts_with("svqrshrun") && i.name.ends_with("_x2"))) + // Skip `svclamp*` intrinsics - not yet implemented! + .filter(|i| !i.name.starts_with("svclamp")) + // Skip `svdot{_lane,}_{s,u}32_{s,u}16` intrinsics - not yet implemented! + .filter(|i| { + i.name != "svdot_lane_u32_u16" + && i.name != "svdot_lane_s32_s16" + && i.name != "svdot_u32_u16" + && i.name != "svdot_s32_s16" + }) + // Skip `svrevd*` intrinsics - not yet implemented! + .filter(|i| !i.name.starts_with("svrevd")) + // Skip `svpsel_lane_b*` intrinsics - not yet implemented! + .filter(|i| !i.name.starts_with("svpsel_lane_b")) // Skip pointers for now, we would probably need to look at the return // type to work out how many elements we need to point to. .filter(|i| !i.arguments.iter().any(|a| a.is_ptr())) From 937c582311ee6daaf60dd099b24bb49c2d882695 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 11 Jun 2026 10:23:23 +0000 Subject: [PATCH 23/77] intrinsic-test: skip SVE intrinsics on big endian SVE intrinsics aren't available on big endian --- library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs | 1 + library/stdarch/crates/intrinsic-test/src/arm/mod.rs | 3 +++ library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs | 3 +++ library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs | 1 + 4 files changed, 8 insertions(+) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs index 06cf78a422285..6050cde84ffad 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs @@ -145,6 +145,7 @@ fn json_to_intrinsic( arguments, results: result_ty, arch_tags: intr.architectures, + extension: intr.simd_isa, }) } diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 9f75e301ace2e..f8b193770a236 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -37,6 +37,7 @@ impl SupportedArchitectureTest for ArmArchitectureTest { } fn create(cli_options: &ProcessedCli) -> Self { + let big_endian = cli_options.target.starts_with("aarch64_be"); let a32 = cli_options.target.starts_with("armv7"); let mut intrinsics = get_neon_intrinsics(&cli_options.filename).expect("Error parsing input file"); @@ -99,6 +100,8 @@ impl SupportedArchitectureTest for ArmArchitectureTest { .filter(|i| !cli_options.skip.contains(&i.name)) // Skip A64-specific intrinsics on A32 .filter(|i| !(a32 && i.arch_tags == vec!["A64".to_string()])) + // Skip SVE intrinsics on big endian + .filter(|i| !(big_endian && (i.extension == "SVE" || i.extension == "SVE2"))) .take(sample_size) .collect::>(); diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs index d69644388a830..7c9de818c1f48 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs @@ -17,6 +17,9 @@ pub struct Intrinsic { /// Any architecture-specific tags. pub arch_tags: Vec, + + /// Specific extension that the intrinsic is from + pub extension: String, } /// Invokes `f` for each combination of the values in the constraint ranges. diff --git a/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs b/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs index 6006d7919f875..7815fba2a0a11 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs @@ -145,5 +145,6 @@ fn xml_to_intrinsic( arguments, results: result.unwrap(), arch_tags: intr.cpuid, + extension: intr.tech, }) } From 922330e68c214bf33c2df6a1528fb8d8fbc3bf20 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 24/77] intrinsic-test: do not test `svundef*` The output of these cannot be compared. --- library/stdarch/crates/intrinsic-test/src/arm/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index f8b193770a236..ee5c3ebddf12b 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -91,6 +91,10 @@ impl SupportedArchitectureTest for ArmArchitectureTest { .filter(|i| !i.name.starts_with("svrevd")) // Skip `svpsel_lane_b*` intrinsics - not yet implemented! .filter(|i| !i.name.starts_with("svpsel_lane_b")) + // Skip `svundef*` intrinsics - to avoid undefined behaviour in Rust, these return + // zeroed vectors in Rust, which are inherently going to be different than the + // undefined vectors returned by the C intrinsics. + .filter(|i| !i.name.starts_with("svundef")) // Skip pointers for now, we would probably need to look at the return // type to work out how many elements we need to point to. .filter(|i| !i.arguments.iter().any(|a| a.is_ptr())) From dabb59e7b34756247966b44663e84246b80d9a3d Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 25/77] intrinsic-test: skip `sveorv*` (llvm-project#203921) `sveorv` intrinsics trigger a miscompile in LLVM where the call to the Rust intrinsic is optimised out and replaced with a zero, which is incorrect. --- library/stdarch/crates/intrinsic-test/src/arm/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index ee5c3ebddf12b..dff0aee5940cf 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -95,6 +95,10 @@ impl SupportedArchitectureTest for ArmArchitectureTest { // zeroed vectors in Rust, which are inherently going to be different than the // undefined vectors returned by the C intrinsics. .filter(|i| !i.name.starts_with("svundef")) + // Skip `sveorv` intrinsics - the code produced by `intrinsic-test` for these + // miscompiles and the Rust intrinsic call gets replaced by a constant zero (see + // llvm/llvm-project#203921). + .filter(|i| !i.name.starts_with("sveorv")) // Skip pointers for now, we would probably need to look at the return // type to work out how many elements we need to point to. .filter(|i| !i.arguments.iter().any(|a| a.is_ptr())) From 6638cf5aa11231259d5f572e7eb2b3f800e74bb7 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 26/77] intrinsic-test: skip `svld*_gather_*` These tests require that we generate test arrays with values that are valid when cast to a pointer, which we don't currently support. --- library/stdarch/crates/intrinsic-test/src/arm/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index dff0aee5940cf..ef4b330dd6fe7 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -99,6 +99,9 @@ impl SupportedArchitectureTest for ArmArchitectureTest { // miscompiles and the Rust intrinsic call gets replaced by a constant zero (see // llvm/llvm-project#203921). .filter(|i| !i.name.starts_with("sveorv")) + // These load intrinsics expect each element in the scalable vector `bases` argument to + // be able to be cast to a pointer, which we don't support generating tests for yet. + .filter(|i| !(i.name.starts_with("svld") && i.name.contains("_gather_"))) // Skip pointers for now, we would probably need to look at the return // type to work out how many elements we need to point to. .filter(|i| !i.arguments.iter().any(|a| a.is_ptr())) From dc2f96485ab31598445276db97266ebc95dfd687 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 15 Jun 2026 10:20:39 +0000 Subject: [PATCH 27/77] intrinsic-test: no SVE testing under GCC GCC quickly ICEs when asked to compile intrinsic-test's wrapper sources. --- library/stdarch/crates/intrinsic-test/src/arm/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index ef4b330dd6fe7..5dec050729754 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -32,6 +32,7 @@ impl SupportedArchitectureTest for ArmArchitectureTest { // GCC uses an extra `-` in the arch name match cli_options.cc_arg_style { CcArgStyle::Clang => vec!["-march=armv8.6a+crypto+crc+dotprod+fp16"], + // SVE tests aren't run under GCC so there are no target features added for SVE CcArgStyle::Gcc => vec!["-march=armv8.6-a+crypto+crc+dotprod+fp16+sha3+sm4"], } } @@ -113,6 +114,12 @@ impl SupportedArchitectureTest for ArmArchitectureTest { .filter(|i| !(a32 && i.arch_tags == vec!["A64".to_string()])) // Skip SVE intrinsics on big endian .filter(|i| !(big_endian && (i.extension == "SVE" || i.extension == "SVE2"))) + // Skip SVE intrinsics when testing against GCC as our wrappers run into ICEs + // See + .filter(|i| { + !(matches!(cli_options.cc_arg_style, CcArgStyle::Gcc) + && (i.extension == "SVE" || i.extension == "SVE2")) + }) .take(sample_size) .collect::>(); From e8ff32d6a97cd8e121a5f6bf4b4b5fe4b16ffb65 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 20 May 2026 12:12:58 +0000 Subject: [PATCH 28/77] intrinsic-test: remove `concatln!` This macro isn't necessary and just makes the generated code being written harder to read compared to multi-line strings. --- .../intrinsic-test/src/common/gen_rust.rs | 180 ++++++++---------- 1 file changed, 84 insertions(+), 96 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index 02f6e40dc06a6..132ede8d9b710 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -32,12 +32,6 @@ macro_rules! wrap_partialeq { wrap_partialeq!(NanEqF16(f16), NanEqF32(f32), NanEqF64(f64)); "#; -macro_rules! concatln { - ($($lines:expr),* $(,)?) => { - concat!($( $lines, "\n" ),*) - }; -} - /// Run rustfmt on the generated source code pub fn run_rustfmt(source_path: &str) { let output = Command::new("rustfmt") @@ -65,11 +59,14 @@ pub fn write_bin_cargo_toml( w: &mut impl std::io::Write, module_count: usize, ) -> std::io::Result<()> { - write!(w, concatln!("[workspace]", "members = ["))?; - for i in 0..module_count { - writeln!(w, " \"mod_{i}\",")?; - } - writeln!(w, "]") + write!( + w, + r#" +[workspace] +members = [{members}] +"#, + members = (0..module_count).format_with(",", |i, fmt| fmt(&format_args!("\"mod_{i}\""))) + ) } /// Writes a `Cargo.toml` for a crate with name `name` to `w` that will contain a single Rust source @@ -77,21 +74,20 @@ pub fn write_bin_cargo_toml( pub fn write_lib_cargo_toml(w: &mut impl std::io::Write, name: &str) -> std::io::Result<()> { write!( w, - concatln!( - "[package]", - "name = \"{name}\"", - "version = \"{version}\"", - "authors = [{authors}]", - "license = \"{license}\"", - "edition = \"2018\"", - "", - "[dependencies]", - "core_arch = {{ path = \"../../crates/core_arch\" }}", - "", - "[build-dependencies]", - "cc = \"1\"" - ), - name = name, + r#" +[package] +name = "{name}" +version = "{version}" +authors = [{authors}] +license = "{license}" +edition = "2018" + +[dependencies] +core_arch = {{ path = "../../crates/core_arch" }} + +[build-dependencies] +cc = "1" +"#, version = env!("CARGO_PKG_VERSION"), authors = env!("CARGO_PKG_AUTHORS") .split(":") @@ -110,22 +106,25 @@ pub fn write_lib_rs( i: usize, intrinsics: &[Intrinsic], ) -> std::io::Result<()> { - write!(w, "{notice}")?; - - writeln!(w, "#![feature(simd_ffi)]")?; - writeln!(w, "#![feature(f16)]")?; - writeln!(w, "#![allow(unused)]")?; - - // Cargo will spam the logs if these warnings are not silenced. - writeln!(w, "#![allow(non_upper_case_globals)]")?; - writeln!(w, "#![allow(non_camel_case_types)]")?; - writeln!(w, "#![allow(non_snake_case)]")?; - - writeln!(w, "{cfg}")?; - - writeln!(w, "{}", COMMON_RUST_DEFINITIONS)?; - - writeln!(w, "{definitions}")?; + writeln!( + w, + r#" +{notice} +#![feature(simd_ffi)] +#![feature(f16)] +#![allow(unused)] + +// Cargo will spam the logs if these warnings are not silenced. +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +{cfg} +{COMMON_RUST_DEFINITIONS} + +{definitions} +"# + )?; let mut seen = std::collections::HashSet::new(); @@ -224,28 +223,25 @@ fn generate_rust_test_loop( write!( w, - concatln!( - " for (id, rust, c) in specializations {{", - " for i in 0..{passes} {{", - " unsafe {{", - "{loaded_args}", - " let __rust_return_value = rust({rust_args});", - "", - " let mut __c_return_value = std::mem::MaybeUninit::uninit();", - " c(__c_return_value.as_mut_ptr(){c_args});", - " let __c_return_value = __c_return_value.assume_init();", - "", - " assert_eq!({cast_prefix}__rust_return_value{cast_suffix}, {cast_prefix}__c_return_value{cast_suffix}, \"{{id}}\");", - " }}", - " }}", - " }}", - ), + r#" +for (id, rust, c) in specializations {{ + for i in 0..{PASSES} {{ + unsafe {{ + {loaded_args} + let __rust_return_value = rust({rust_args}); + + let mut __c_return_value = std::mem::MaybeUninit::uninit(); + c(__c_return_value.as_mut_ptr(){c_args}); + let __c_return_value = __c_return_value.assume_init(); + + assert_eq!({cast_prefix}__rust_return_value{cast_suffix}, {cast_prefix}__c_return_value{cast_suffix}, "{{id}}"); + }} + }} +}} +"#, loaded_args = intrinsic.arguments.load_values_rust(), rust_args = intrinsic.arguments.as_call_param_rust(), c_args = intrinsic.arguments.as_c_call_param_rust(), - passes = PASSES, - cast_prefix = cast_prefix, - cast_suffix = cast_suffix, ) } @@ -259,7 +255,10 @@ fn create_rust_test( write!( w, - concatln!("#[test]", "fn test_{intrinsic_name}() {{"), + r#" +#[test] +fn test_{intrinsic_name}() {{ +"#, intrinsic_name = intrinsic.name, )?; @@ -279,19 +278,18 @@ pub fn write_bindings_rust( ) -> std::io::Result<()> { write!( w, - concatln!( - "#[allow(improper_ctypes)]", - "#[link(name = \"wrapper_{i}\")]", - "unsafe extern \"C\" {{" - ), - i = i + r#" +#[allow(improper_ctypes)] +#[link(name = "wrapper_{i}")] +unsafe extern "C" {{ +"#, )?; for intrinsic in intrinsics { intrinsic.iter_specializations(|imm_values| { writeln!( w, - " fn {name}_wrapper{imm_arglist}(__dst: *mut {return_ty}{arglist});", + "fn {name}_wrapper{imm_arglist}(__dst: *mut {return_ty}{arglist});", return_ty = intrinsic.results.rust_type(), name = intrinsic.name, imm_arglist = imm_values @@ -326,32 +324,22 @@ pub fn write_build_rs( write!( w, - concatln!( - "fn main() {{", - " cc::Build::new()", - " .file(\"../../c_programs/wrapper_{i}.c\")", - " .opt_level(2)", - " .flags(&[", - ), - i = i - )?; - - let compiler_specific_flags = match cli_options.cc_arg_style { - CcArgStyle::Gcc => GCC_FLAGS, - CcArgStyle::Clang => CLANG_FLAGS, - }; - - for flag in COMMON_FLAGS - .iter() - .chain(compiler_specific_flags) - .chain(arch_flags) - { - writeln!(w, "\"{flag}\",")?; - } - - write!( - w, - concatln!(" ])", " .compile(\"wrapper_{i}\");", "}}"), - i = i + r#" +fn main() {{ + cc::Build::new() + .file("../../c_programs/wrapper_{i}.c") + .opt_level(2) + .flags(&[{flags}]) + .compile("wrapper_{i}"); +}} +"#, + flags = COMMON_FLAGS + .iter() + .chain(match cli_options.cc_arg_style { + CcArgStyle::Gcc => GCC_FLAGS, + CcArgStyle::Clang => CLANG_FLAGS, + }) + .chain(arch_flags) + .format_with(",", |flag, fmt| fmt(&format_args!("\"{flag}\""))), ) } From 92ca3a554c1922877ed0e50f8723713fa39a5ebb Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 9 Jun 2026 08:44:17 +0000 Subject: [PATCH 29/77] intrinsic-test: remove unnecessary newlines All of the generated output is run through rustfmt so these aren't necessary. --- library/stdarch/crates/intrinsic-test/src/common/argument.rs | 4 ++-- library/stdarch/crates/intrinsic-test/src/common/values.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/common/argument.rs b/library/stdarch/crates/intrinsic-test/src/common/argument.rs index eaec5b71c47e3..f1d87f6dedd7e 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/argument.rs @@ -179,14 +179,14 @@ where .map(|(idx, arg)| { if arg.is_simd() { format!( - "let {name} = {load}({vals_name}.as_ptr().add((i+{idx}) % {PASSES}) as _);\n", + "let {name} = {load}({vals_name}.as_ptr().add((i+{idx}) % {PASSES}) as _);", name = arg.generate_name(), vals_name = test_values_array_name(&arg.ty), load = arg.ty.get_load_function(), ) } else { format!( - "let {name} = {vals_name}[(i+{idx}) % {PASSES}];\n", + "let {name} = {vals_name}[(i+{idx}) % {PASSES}];", name = arg.generate_name(), vals_name = test_values_array_name(&arg.ty), ) diff --git a/library/stdarch/crates/intrinsic-test/src/common/values.rs b/library/stdarch/crates/intrinsic-test/src/common/values.rs index 4c3dd078e034f..f7bd4a4eab58d 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/values.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/values.rs @@ -24,7 +24,7 @@ pub fn test_values_array_static( ) -> std::io::Result<()> { writeln!( w, - "static {name}: [{ty}; {load_size}] = {values};\n", + "static {name}: [{ty}; {load_size}] = {values};", name = test_values_array_name(ty), ty = ty.rust_scalar_type(), load_size = test_values_array_length(&ty), From c2c6cb43e85a0c98585b74dcbf142ec42a7e38ef Mon Sep 17 00:00:00 2001 From: xmakro Date: Fri, 19 Jun 2026 19:27:51 -0700 Subject: [PATCH 30/77] Fix too-short variance slice in `variances_of` cycle recovery --- compiler/rustc_query_impl/src/handle_cycle_error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs index 79e7788cafe81..2beef6d6e3367 100644 --- a/compiler/rustc_query_impl/src/handle_cycle_error.rs +++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs @@ -104,7 +104,7 @@ pub(crate) fn variances_of<'tcx>( err: Diag<'_>, ) -> &'tcx [ty::Variance] { let _guar = err.delay_as_bug(); - let n = tcx.generics_of(def_id).own_params.len(); + let n = tcx.generics_of(def_id).count(); tcx.arena.alloc_from_iter(iter::repeat_n(ty::Bivariant, n)) } From 77a83f264f995eb1956ab390623c2e321d4fa1d0 Mon Sep 17 00:00:00 2001 From: xonx <119700621+xonx4l@users.noreply.github.com> Date: Tue, 9 Jun 2026 17:43:11 +0000 Subject: [PATCH 31/77] Add stdarch-gen-common --- library/stdarch/.github/workflows/main.yml | 2 + library/stdarch/Cargo.lock | 62 +++ .../crates/core_arch/src/hexagon/v128.rs | 1 + .../crates/core_arch/src/hexagon/v64.rs | 1 + .../crates/stdarch-gen-common/Cargo.toml | 7 + .../crates/stdarch-gen-common/src/lib.rs | 352 ++++++++++++++++++ .../crates/stdarch-gen-hexagon/Cargo.toml | 1 + .../crates/stdarch-gen-hexagon/src/main.rs | 34 +- 8 files changed, 443 insertions(+), 17 deletions(-) create mode 100644 library/stdarch/crates/stdarch-gen-common/Cargo.toml create mode 100644 library/stdarch/crates/stdarch-gen-common/src/lib.rs diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 98f6b842d135f..6333b32ab8ad4 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -337,6 +337,8 @@ jobs: cargo run --bin=stdarch-gen-loongarch --release -- crates/stdarch-gen-loongarch/lasx.spec git diff --exit-code - name: Check hexagon + env: + STDARCH_GEN_MODE: check run: | cargo run -p stdarch-gen-hexagon --release git diff --exit-code diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 804879c8fdc6a..c8cfc21a5a1a1 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -268,6 +268,22 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -446,6 +462,12 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + [[package]] name = "log" version = "0.4.29" @@ -458,6 +480,12 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + [[package]] name = "once_cell_polyfill" version = "1.70.2" @@ -654,6 +682,19 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.23" @@ -793,11 +834,19 @@ dependencies = [ "walkdir", ] +[[package]] +name = "stdarch-gen-common" +version = "0.1.0" +dependencies = [ + "tempfile", +] + [[package]] name = "stdarch-gen-hexagon" version = "0.1.0" dependencies = [ "regex", + "stdarch-gen-common", ] [[package]] @@ -870,6 +919,19 @@ version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d0e35dc7d73976a53c7e6d7d177ef804a0c0ee774ec77bcc520c2216fd7cbe" +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys", +] + [[package]] name = "termcolor" version = "1.4.1" diff --git a/library/stdarch/crates/core_arch/src/hexagon/v128.rs b/library/stdarch/crates/core_arch/src/hexagon/v128.rs index 1f0566af78ef3..1a1826ddda316 100644 --- a/library/stdarch/crates/core_arch/src/hexagon/v128.rs +++ b/library/stdarch/crates/core_arch/src/hexagon/v128.rs @@ -1,3 +1,4 @@ +// This code is automatically generated. DO NOT MODIFY. //! Hexagon HVX 128-byte vector mode intrinsics //! //! This module provides intrinsics for the Hexagon Vector Extensions (HVX) diff --git a/library/stdarch/crates/core_arch/src/hexagon/v64.rs b/library/stdarch/crates/core_arch/src/hexagon/v64.rs index e9b18b2fd8efe..3ac8b47079333 100644 --- a/library/stdarch/crates/core_arch/src/hexagon/v64.rs +++ b/library/stdarch/crates/core_arch/src/hexagon/v64.rs @@ -1,3 +1,4 @@ +// This code is automatically generated. DO NOT MODIFY. //! Hexagon HVX 64-byte vector mode intrinsics //! //! This module provides intrinsics for the Hexagon Vector Extensions (HVX) diff --git a/library/stdarch/crates/stdarch-gen-common/Cargo.toml b/library/stdarch/crates/stdarch-gen-common/Cargo.toml new file mode 100644 index 0000000000000..691be14971a0d --- /dev/null +++ b/library/stdarch/crates/stdarch-gen-common/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "stdarch-gen-common" +version = "0.1.0" +edition = "2024" + +[dependencies] +tempfile = "3" \ No newline at end of file diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs new file mode 100644 index 0000000000000..13d788594ca55 --- /dev/null +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -0,0 +1,352 @@ +//! Shared check/bless harness for stdarch generators. + +use std::error::Error as StdError; +use std::fmt; +use std::fs; +use std::io; +use std::io::Read; +use std::path::{Path, PathBuf}; + +/// First-line marker identifying an auto-generated file. Generators emit this +/// as the first line of every file they produce; the harness uses it to +/// discover which files in `committed` are owned by the generator. +pub const GENERATED_MARKER: &str = "// This code is automatically generated. DO NOT MODIFY."; + +/// Controls what `run_generator` does with the generator's output. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Mode { + /// Verify that the `committed` matches the generator's output for owned files. + /// + /// Runs the generator into a temp directory, then compares each produced + /// file against the committed copy. Returns an error on the first mismatch. + Check, + /// Update the `committed` to match the generator's output for owned files. + /// + /// Runs the generator into a temp directory and copies each produced file + /// into `committed`. If the generator no longer produces an owned file, the + /// committed copy is deleted. Files in `committed` that are not owned + /// are left untouched. + Bless, +} + +impl Mode { + /// Read the mode from the `STDARCH_GEN_MODE` environment variable. + /// + /// Recognized values: + /// - `"check"` → [`Mode::Check`] + /// - `"bless"` → [`Mode::Bless`] + /// - unset → [`Mode::Bless`] + /// - any other value → panic + pub fn from_env() -> Self { + match std::env::var("STDARCH_GEN_MODE").as_deref() { + Ok("check") => Mode::Check, + Ok("bless") => Mode::Bless, + Ok(other) => panic!("unknown STDARCH_GEN_MODE value: {other:?}"), + Err(_) => Mode::Bless, + } + } +} + +#[derive(Debug)] +pub enum Error { + Io(io::Error), + Mismatch { path: PathBuf, kind: MismatchKind }, + Generator(Box), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MismatchKind { + /// Owned file produced by the generator but absent from the `committed`. + /// Means the `committed` needs to be regenerated. + MissingInCommitted, + /// Owned file present in the `committed` but the generator no longer + /// produces it. The file must be removed from the `committed` . + ExtraInCommitted, + /// Owned file exists on both sides but contents differ. + ContentsDiffer, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Io(e) => write!(f, "I/O error: {e}"), + Error::Mismatch { path, kind } => match kind { + MismatchKind::MissingInCommitted => { + write!(f, "{}: generated but not committed", path.display()) + } + MismatchKind::ExtraInCommitted => { + write!(f, "{}: committed but no longer generated", path.display()) + } + MismatchKind::ContentsDiffer => write!(f, "{}: contents differ", path.display()), + }, + Error::Generator(e) => write!(f, "generator failed: {e}"), + } + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match self { + Error::Io(e) => Some(e), + Error::Generator(e) => Some(&**e), + _ => None, + } + } +} + +impl From for Error { + fn from(e: io::Error) -> Self { + Error::Io(e) + } +} + +pub type Result = std::result::Result; + +/// Run a generator under the chosen `mode`, reconciling its output with `committed`. +/// +/// Arguments: +/// - `committed` — the directory holding the in-tree (committed) source files. +/// Files inside `committed` whose first line begins with [`GENERATED_MARKER`] +/// are treated as owned by the generator. Anything else is treated as +/// hand-written and is left untouched by `Bless` and ignored by `Check`. +/// So generated files coexist with hand-written files in the same directory. +/// - `mode` — what to do with the generator's output. +/// - `generate` — closure that writes the generator's output into the +/// directory it is given. Its error is wrapped in [`Error::Generator`]. +/// +/// Behavior per mode: +/// - [`Mode::Check`]: runs the generator into a temp dir and compares owned +/// files against the committed copies. Mismatch returns [`Error::Mismatch`]. +/// - [`Mode::Bless`]: runs the generator into a temp dir and copies owned +/// files into `committed`, or removes `committed`'s copy if the generator no +/// longer produces them. +pub fn run_generator(committed: &Path, mode: Mode, generate: F) -> Result<()> +where + F: FnOnce(&Path) -> std::result::Result<(), E>, + E: Into>, +{ + let scratch = tempfile::tempdir()?; + generate(scratch.path()).map_err(|e| Error::Generator(e.into()))?; + + let owned = discover_owned(committed)?; + let produced = discover_all(scratch.path())?; + + let mut names: Vec<&String> = owned.iter().chain(produced.iter()).collect(); + names.sort(); + names.dedup(); + + for name in names { + match mode { + Mode::Check => compare(scratch.path(), committed, name)?, + Mode::Bless => apply_bless(scratch.path(), committed, name)?, + } + } + Ok(()) +} + +/// Returns the names of files in `dir` whose first line begins with +/// [`GENERATED_MARKER`]. Files without the marker are skipped. +fn discover_owned(dir: &Path) -> Result> { + let mut out = Vec::new(); + for entry in fs::read_dir(dir)? { + let entry = entry?; + if !entry.file_type()?.is_file() { + continue; + } + let Ok(mut file) = fs::File::open(entry.path()) else { + continue; + }; + let mut buf = [0u8; GENERATED_MARKER.len()]; + if file.read_exact(&mut buf).is_err() { + continue; + } + if buf == *GENERATED_MARKER.as_bytes() + && let Some(name) = entry.file_name().to_str() + { + out.push(name.to_owned()); + } + } + out.sort(); + Ok(out) +} + +/// Returns every file name in `dir` (scratch dir — all files are generator output). +fn discover_all(dir: &Path) -> Result> { + let mut out = Vec::new(); + for entry in fs::read_dir(dir)? { + let entry = entry?; + if entry.file_type()?.is_file() + && let Some(name) = entry.file_name().to_str() + { + out.push(name.to_string()); + } + } + Ok(out) +} + +fn compare(generated_dir: &Path, committed_dir: &Path, filename: &str) -> Result<()> { + let rel_path = PathBuf::from(filename); + let gen_path = generated_dir.join(&rel_path); + let comm_path = committed_dir.join(&rel_path); + match (gen_path.exists(), comm_path.exists()) { + (true, false) => Err(Error::Mismatch { + path: rel_path, + kind: MismatchKind::MissingInCommitted, + }), + (false, true) => Err(Error::Mismatch { + path: rel_path, + kind: MismatchKind::ExtraInCommitted, + }), + (false, false) => Ok(()), + (true, true) => { + if fs::read(&gen_path)? != fs::read(&comm_path)? { + Err(Error::Mismatch { + path: rel_path, + kind: MismatchKind::ContentsDiffer, + }) + } else { + Ok(()) + } + } + } +} + +fn apply_bless(generated_dir: &Path, committed_dir: &Path, filename: &str) -> Result<()> { + fs::create_dir_all(committed_dir)?; + let rel_path = PathBuf::from(filename); + let from = generated_dir.join(&rel_path); + let to = committed_dir.join(&rel_path); + if from.exists() { + if let Some(parent) = to.parent() { + fs::create_dir_all(parent)?; + } + fs::copy(&from, &to)?; + } else if to.exists() { + fs::remove_file(&to)?; + } + Ok(()) +} + +// Skipped on iOS because these tests fail on the `x86_64-apple-ios-macabi` CI runner +// with `Os { code: 17, kind: AlreadyExists, message: "File exists" }`. +#[cfg(all(test, not(target_os = "ios")))] +mod tests { + use super::*; + + fn write_marker(p: &Path, body: &[u8]) { + if let Some(d) = p.parent() { + fs::create_dir_all(d).unwrap(); + } + let mut bytes = Vec::new(); + bytes.extend_from_slice(GENERATED_MARKER.as_bytes()); + bytes.push(b'\n'); + bytes.extend_from_slice(body); + fs::write(p, bytes).unwrap(); + } + + #[test] + fn check_fails_on_byte_diff() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + write_marker(&committed.join("a.txt"), b"hi"); + let e = run_generator( + &committed, + Mode::Check, + |out| -> std::result::Result<(), io::Error> { + write_marker(&out.join("a.txt"), b"HI"); + Ok(()) + }, + ) + .unwrap_err(); + assert!(matches!( + e, + Error::Mismatch { + kind: MismatchKind::ContentsDiffer, + .. + } + )); + } + + #[test] + fn check_fails_when_owned_file_missing_from_generated() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + write_marker(&committed.join("a.txt"), b"hi"); + let e = run_generator( + &committed, + Mode::Check, + |_| -> std::result::Result<(), io::Error> { Ok(()) }, + ) + .unwrap_err(); + assert!(matches!( + e, + Error::Mismatch { + kind: MismatchKind::ExtraInCommitted, + .. + } + )); + } + + #[test] + fn check_fails_when_owned_file_missing_from_committed() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + fs::create_dir_all(&committed).unwrap(); + let e = run_generator( + &committed, + Mode::Check, + |out| -> std::result::Result<(), io::Error> { + write_marker(&out.join("a.txt"), b"hi"); + Ok(()) + }, + ) + .unwrap_err(); + assert!(matches!( + e, + Error::Mismatch { + kind: MismatchKind::MissingInCommitted, + .. + } + )); + } + + #[test] + fn bless_deletes_files_no_longer_produced() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + write_marker(&committed.join("keep.txt"), b""); + write_marker(&committed.join("stale.txt"), b""); + run_generator( + &committed, + Mode::Bless, + |out| -> std::result::Result<(), io::Error> { + write_marker(&out.join("keep.txt"), b""); + Ok(()) + }, + ) + .unwrap(); + assert!(committed.join("keep.txt").exists()); + assert!(!committed.join("stale.txt").exists()); + } + + #[test] + fn bless_preserves_unowned_files() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + fs::create_dir_all(&committed).unwrap(); + fs::write(committed.join("mod.rs"), b"hand-written").unwrap(); + fs::write(committed.join("old.txt"), b"old").unwrap(); + run_generator( + &committed, + Mode::Bless, + |out| -> std::result::Result<(), io::Error> { + write_marker(&out.join("new.txt"), b"new"); + Ok(()) + }, + ) + .unwrap(); + assert_eq!(fs::read(committed.join("mod.rs")).unwrap(), b"hand-written"); + assert_eq!(fs::read(committed.join("old.txt")).unwrap(), b"old"); + assert!(committed.join("new.txt").exists()); + } +} diff --git a/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml b/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml index 397c7816f8d1e..c7dfce2c0fd7b 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] regex = "1.10" +stdarch-gen-common = { path = "../stdarch-gen-common" } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs index 7a1c3030c0042..c3ad153ab0a7a 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs @@ -21,6 +21,7 @@ use std::collections::{HashMap, HashSet}; use std::fs::File; use std::io::Write; use std::path::Path; +use stdarch_gen_common::{run_generator, Mode, GENERATED_MARKER}; /// Mappings from HVX intrinsics to architecture-independent SIMD intrinsics. /// These intrinsics have equivalent semantics and can be lowered to the generic form. @@ -1609,6 +1610,7 @@ fn generate_module_file( let mut output = File::create(output_path).map_err(|e| format!("Failed to create output: {}", e))?; + writeln!(output, "{}", GENERATED_MARKER).map_err(|e| e.to_string())?; writeln!(output, "{}", generate_module_doc(mode)).map_err(|e| e.to_string())?; writeln!(output, "{}", generate_types(mode)).map_err(|e| e.to_string())?; writeln!(output, "{}", generate_extern_block(intrinsics, mode)).map_err(|e| e.to_string())?; @@ -1691,23 +1693,21 @@ fn main() -> Result<(), String> { } // Generate output files - let hexagon_dir = std::env::args() - .nth(1) - .map(std::path::PathBuf::from) - .unwrap_or_else(|| crate_dir.join("../core_arch/src/hexagon")); - std::fs::create_dir_all(&hexagon_dir).map_err(|e| e.to_string())?; - - // Generate v64.rs (64-byte vector mode) - let v64_path = hexagon_dir.join("v64.rs"); - println!("\nStep 3: Generating v64.rs (64-byte mode)..."); - generate_module_file(&intrinsics, &v64_path, VectorMode::V64)?; - println!(" Output: {}", v64_path.display()); - - // Generate v128.rs (128-byte vector mode) - let v128_path = hexagon_dir.join("v128.rs"); - println!("\nStep 4: Generating v128.rs (128-byte mode)..."); - generate_module_file(&intrinsics, &v128_path, VectorMode::V128)?; - println!(" Output: {}", v128_path.display()); + let hexagon_dir = crate_dir.join("../core_arch/src/hexagon"); + + // Either "check" to check the output versus the committed output, or "bless" + // to update the output. + let mode = Mode::from_env(); + println!("\nStep 3: Generating v64.rs and v128.rs (mode: {mode:?})..."); + run_generator(&hexagon_dir, mode, |out_dir| -> Result<(), String> { + for (filename, vmode) in [("v64.rs", VectorMode::V64), ("v128.rs", VectorMode::V128)] { + let path = out_dir.join(filename); + generate_module_file(&intrinsics, &path, vmode)?; + println!(" Output: {}", hexagon_dir.join(filename).display()); + } + Ok(()) + }) + .map_err(|e| e.to_string())?; println!("\n=== Results ==="); println!( From 80844b8595e70aa46541c0e9e4ba99dd14994936 Mon Sep 17 00:00:00 2001 From: xmakro Date: Thu, 11 Jun 2026 10:16:40 -0700 Subject: [PATCH 32/77] perf: drop the full-crate AST walk in check_unused --- compiler/rustc_resolve/src/check_unused.rs | 13 ++++++----- compiler/rustc_resolve/src/late.rs | 25 +++++++++++++++------- compiler/rustc_resolve/src/lib.rs | 5 +++-- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 32e4bb9262fa8..4c5c591ad94e3 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -10,9 +10,9 @@ // // Checking for unused imports is split into three steps: // -// - `UnusedImportCheckVisitor` walks the AST to find all the unused imports -// inside of `UseTree`s, recording their `NodeId`s and grouping them by -// the parent `use` item +// - `UnusedImportCheckVisitor` visits the `use` items collected during late +// resolution to find all the unused imports inside of `UseTree`s, recording +// their `NodeId`s and grouping them by the parent `use` item // // - `calc_unused_spans` then walks over all the `use` items marked in the // previous step to collect the spans associated with the `NodeId`s and to @@ -410,7 +410,7 @@ fn calc_unused_spans( } impl Resolver<'_, '_> { - pub(crate) fn check_unused(&mut self, krate: &ast::Crate) { + pub(crate) fn check_unused(&mut self, use_items: Vec<&ast::Item>) { let tcx = self.tcx; let mut maybe_unused_extern_crates = FxHashMap::default(); @@ -465,7 +465,10 @@ impl Resolver<'_, '_> { base_id: ast::DUMMY_NODE_ID, item_span: DUMMY_SP, }; - visit::walk_crate(&mut visitor, krate); + // `use_items` is in crate DFS order, so diagnostics and side effects are unchanged. + for item in use_items { + visitor.visit_item(item); + } visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5ae2aaadffae7..bf9d6370092ff 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5587,12 +5587,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } /// Walks the whole crate in DFS order, visiting each item, counting the declared number of -/// lifetime generic parameters and function parameters. -struct ItemInfoCollector<'a, 'ra, 'tcx> { +/// lifetime generic parameters and function parameters. Also collects all `use` and +/// `extern crate` items so that `check_unused` doesn't need to walk the crate again. +struct ItemInfoCollector<'a, 'ast, 'ra, 'tcx> { r: &'a mut Resolver<'ra, 'tcx>, + /// All `use` and `extern crate` items, in the order in which they are visited. + use_items: Vec<&'ast Item>, } -impl ItemInfoCollector<'_, '_, '_> { +impl ItemInfoCollector<'_, '_, '_, '_> { fn collect_fn_info(&mut self, decl: &FnDecl, id: NodeId) { self.r .delegation_fn_sigs @@ -5626,7 +5629,7 @@ fn required_generic_args_suggestion(generics: &ast::Generics) -> Option if required.is_empty() { None } else { Some(format!("<{}>", required.join(", "))) } } -impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { +impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, 'ast, '_, '_> { fn visit_item(&mut self, item: &'ast Item) { match &item.kind { ItemKind::TyAlias(TyAlias { generics, .. }) @@ -5659,11 +5662,13 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } } + ItemKind::Use(..) | ItemKind::ExternCrate(..) => { + self.use_items.push(item); + } + ItemKind::Mod(..) | ItemKind::Static(..) | ItemKind::ConstBlock(..) - | ItemKind::Use(..) - | ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) | ItemKind::MacCall(..) @@ -5694,9 +5699,12 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } impl<'ra, 'tcx> Resolver<'ra, 'tcx> { - pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { + /// Returns the `use` and `extern crate` items of the crate, for use by `check_unused`. + pub(crate) fn late_resolve_crate<'ast>(&mut self, krate: &'ast Crate) -> Vec<&'ast Item> { with_owner(self, CRATE_NODE_ID, |this| { - visit::walk_crate(&mut ItemInfoCollector { r: this }, krate); + let mut info_collector = ItemInfoCollector { r: this, use_items: Vec::new() }; + visit::walk_crate(&mut info_collector, krate); + let use_items = info_collector.use_items; let mut late_resolution_visitor = LateResolutionVisitor::new(this); late_resolution_visitor .resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); @@ -5709,6 +5717,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { crate::diagnostics::UnusedLabel, ); } + use_items }) } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 061471ccc97e0..b8c9d42f6a6ab 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2082,9 +2082,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.tcx .sess .time("finalize_macro_resolutions", || self.finalize_macro_resolutions(krate)); - self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate)); + let use_items = + self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate)); self.tcx.sess.time("resolve_main", || self.resolve_main()); - self.tcx.sess.time("resolve_check_unused", || self.check_unused(krate)); + self.tcx.sess.time("resolve_check_unused", || self.check_unused(use_items)); self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate)); self.tcx .sess From 9558c381000c3d060872043746887ec29e1b4930 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 2 Jun 2026 12:39:02 +0000 Subject: [PATCH 33/77] intrinsic-test: shorten various type names This isn't strictly necessary but these type names were longer than they needed to be. --- .../crates/intrinsic-test/src/arm/intrinsic.rs | 6 +++--- .../intrinsic-test/src/arm/json_parser.rs | 18 +++++++----------- .../crates/intrinsic-test/src/arm/mod.rs | 18 ++++++++---------- .../crates/intrinsic-test/src/arm/types.rs | 8 +++----- .../intrinsic-test/src/common/argument.rs | 10 +++++----- .../crates/intrinsic-test/src/common/gen_c.rs | 4 ++-- .../intrinsic-test/src/common/gen_rust.rs | 10 +++++----- .../intrinsic-test/src/common/intrinsic.rs | 6 +++--- .../src/common/intrinsic_helpers.rs | 2 +- .../crates/intrinsic-test/src/common/mod.rs | 8 ++++---- .../crates/intrinsic-test/src/common/values.rs | 6 +++--- .../stdarch/crates/intrinsic-test/src/main.rs | 18 ++++++------------ .../crates/intrinsic-test/src/x86/mod.rs | 8 ++++---- .../crates/intrinsic-test/src/x86/types.rs | 6 ++---- 14 files changed, 56 insertions(+), 72 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs index a54e5857192e0..bcbee3503b9ad 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs @@ -2,9 +2,9 @@ use crate::common::intrinsic_helpers::IntrinsicType; use std::ops::{Deref, DerefMut}; #[derive(Debug, Clone, PartialEq)] -pub struct ArmIntrinsicType(pub IntrinsicType); +pub struct ArmType(pub IntrinsicType); -impl Deref for ArmIntrinsicType { +impl Deref for ArmType { type Target = IntrinsicType; fn deref(&self) -> &Self::Target { @@ -12,7 +12,7 @@ impl Deref for ArmIntrinsicType { } } -impl DerefMut for ArmIntrinsicType { +impl DerefMut for ArmType { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } diff --git a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs index 6050cde84ffad..ebbde115aa4bf 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs @@ -1,4 +1,4 @@ -use super::intrinsic::ArmIntrinsicType; +use super::intrinsic::ArmType; use crate::arm::types::parse_intrinsic_type; use crate::common::argument::{Argument, ArgumentList}; use crate::common::constraint::Constraint; @@ -59,7 +59,7 @@ struct JsonIntrinsic { pub fn get_neon_intrinsics( filename: &Path, -) -> Result>, Box> { +) -> Result>, Box> { let file = std::fs::File::open(filename)?; let reader = std::io::BufReader::new(file); let json: Vec = serde_json::from_reader(reader).expect("Couldn't parse JSON"); @@ -79,10 +79,10 @@ pub fn get_neon_intrinsics( fn json_to_intrinsic( mut intr: JsonIntrinsic, -) -> Result, Box> { +) -> Result, Box> { let name = intr.name.replace(['[', ']'], ""); - let result_ty = ArmIntrinsicType(parse_intrinsic_type(&intr.return_type.value)?); + let result_ty = ArmType(parse_intrinsic_type(&intr.return_type.value)?); let args = intr .arguments @@ -120,12 +120,8 @@ fn json_to_intrinsic( } }); - let mut arg = Argument::::new( - i, - String::from(arg_name), - ArmIntrinsicType(arg_ty), - constraint, - ); + let mut arg = + Argument::::new(i, String::from(arg_name), ArmType(arg_ty), constraint); // The JSON doesn't list immediates as const let IntrinsicType { @@ -138,7 +134,7 @@ fn json_to_intrinsic( }) .collect(); - let arguments = ArgumentList:: { args }; + let arguments = ArgumentList:: { args }; Ok(Intrinsic { name, diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 5dec050729754..0c5aa5da929de 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -3,22 +3,20 @@ mod intrinsic; mod json_parser; mod types; -use crate::common::SupportedArchitectureTest; +use crate::common::SupportedArchitecture; use crate::common::cli::{CcArgStyle, ProcessedCli}; use crate::common::intrinsic::Intrinsic; use crate::common::intrinsic_helpers::{SimdLen, TypeKind}; -use intrinsic::ArmIntrinsicType; +use intrinsic::ArmType; use json_parser::get_neon_intrinsics; -pub struct ArmArchitectureTest { - intrinsics: Vec>, -} +pub struct Arm(Vec>); -impl SupportedArchitectureTest for ArmArchitectureTest { - type IntrinsicImpl = ArmIntrinsicType; +impl SupportedArchitecture for Arm { + type Type = ArmType; - fn intrinsics(&self) -> &[Intrinsic] { - &self.intrinsics + fn intrinsics(&self) -> &[Intrinsic] { + &self.0 } const NOTICE: &str = config::NOTICE; @@ -123,6 +121,6 @@ impl SupportedArchitectureTest for ArmArchitectureTest { .take(sample_size) .collect::>(); - Self { intrinsics } + Self(intrinsics) } } diff --git a/library/stdarch/crates/intrinsic-test/src/arm/types.rs b/library/stdarch/crates/intrinsic-test/src/arm/types.rs index cd420f10678fc..44af107eb96e5 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/types.rs @@ -1,9 +1,7 @@ -use super::intrinsic::ArmIntrinsicType; -use crate::common::intrinsic_helpers::{ - IntrinsicType, IntrinsicTypeDefinition, Sign, SimdLen, TypeKind, -}; +use super::intrinsic::ArmType; +use crate::common::intrinsic_helpers::{IntrinsicType, Sign, SimdLen, TypeDefinition, TypeKind}; -impl IntrinsicTypeDefinition for ArmIntrinsicType { +impl TypeDefinition for ArmType { /// Gets a string containing the typename for this type in C format. fn c_type(&self) -> String { let prefix = self.kind.c_prefix(); diff --git a/library/stdarch/crates/intrinsic-test/src/common/argument.rs b/library/stdarch/crates/intrinsic-test/src/common/argument.rs index f1d87f6dedd7e..e91a9ab7735e1 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/argument.rs @@ -5,11 +5,11 @@ use crate::common::values::test_values_array_name; use super::PASSES; use super::constraint::Constraint; -use super::intrinsic_helpers::IntrinsicTypeDefinition; +use super::intrinsic_helpers::TypeDefinition; /// An argument for the intrinsic. #[derive(Debug, PartialEq, Clone)] -pub struct Argument { +pub struct Argument { /// The argument's index in the intrinsic function call. pub pos: usize, /// The argument name. @@ -22,7 +22,7 @@ pub struct Argument { impl Argument where - T: IntrinsicTypeDefinition, + T: TypeDefinition, { pub fn new(pos: usize, name: String, ty: T, constraint: Option) -> Self { Argument { @@ -63,13 +63,13 @@ where /// Arguments of an intrinsic - including parameters that end up being const generics. #[derive(Debug, PartialEq, Clone)] -pub struct ArgumentList { +pub struct ArgumentList { pub args: Vec>, } impl ArgumentList where - T: IntrinsicTypeDefinition, + T: TypeDefinition, { /// Returns a string with the arguments in `self` as a parameter list for a wrapper fn /// definition in C (e.g. `$ty1 $arg1, $ty2 $arg2`). diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index 24756324c48e4..888f5b2805d08 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use crate::common::intrinsic::Intrinsic; -use super::intrinsic_helpers::IntrinsicTypeDefinition; +use super::intrinsic_helpers::TypeDefinition; /// Generates a C source file containing wrapper functions around each specialisation of each /// intrinsic (that is, intrinsics with specific values for the the immediate arguments). Each @@ -14,7 +14,7 @@ use super::intrinsic_helpers::IntrinsicTypeDefinition; /// *__dst = __crc32cd(a, b); /// } /// ``` -pub fn write_wrapper_c( +pub fn write_wrapper_c( w: &mut impl std::io::Write, notice: &str, platform_headers: &[&str], diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index 132ede8d9b710..36f5754367474 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -2,7 +2,7 @@ use std::process::Command; use itertools::Itertools; -use super::intrinsic_helpers::IntrinsicTypeDefinition; +use super::intrinsic_helpers::TypeDefinition; use crate::common::PASSES; use crate::common::cli::{CcArgStyle, ProcessedCli}; use crate::common::intrinsic::Intrinsic; @@ -98,7 +98,7 @@ cc = "1" /// Writes a Rust source file into `w` with common definitions, static arrays with test values, /// declarations of C wrapper functions for FFI and Rust test functions. -pub fn write_lib_rs( +pub fn write_lib_rs( w: &mut impl std::io::Write, notice: &str, cfg: &str, @@ -156,7 +156,7 @@ pub fn write_lib_rs( /// (first loop) `PASSES` number of times (second loop). For a given iteration of a given /// specialisation, test values are loaded for each argument and passed to the Rust intrinsic /// and the C wrapper function, and the results are compared. -fn generate_rust_test_loop( +fn generate_rust_test_loop( w: &mut impl std::io::Write, intrinsic: &Intrinsic, ) -> std::io::Result<()> { @@ -247,7 +247,7 @@ for (id, rust, c) in specializations {{ /// Writes a test function for an given intrinsic to `w`, with a body generated by /// `generate_rust_test_loop`. -fn create_rust_test( +fn create_rust_test( w: &mut impl std::io::Write, intrinsic: &Intrinsic, ) -> std::io::Result<()> { @@ -271,7 +271,7 @@ fn test_{intrinsic_name}() {{ /// Writes an `extern "C"` block with function declarations for each of the C wrapper functions into /// `w`. -pub fn write_bindings_rust( +pub fn write_bindings_rust( w: &mut impl std::io::Write, i: usize, intrinsics: &[Intrinsic], diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs index 7c9de818c1f48..ca59385c3b4e2 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs @@ -1,11 +1,11 @@ use crate::common::constraint::Constraint; use super::argument::ArgumentList; -use super::intrinsic_helpers::IntrinsicTypeDefinition; +use super::intrinsic_helpers::TypeDefinition; /// An intrinsic #[derive(Debug, PartialEq, Clone)] -pub struct Intrinsic { +pub struct Intrinsic { /// The function name of this intrinsic. pub name: String, @@ -43,7 +43,7 @@ fn recurse_specializations<'a, E>( } } -impl Intrinsic { +impl Intrinsic { /// Invokes `f` for "specialisation" of the intrinsic - a specific instantiation of the /// constant generics of the intrinsic. `f` takes a slice where the `i`th element corresponds /// to the value of the `i`th const generic argument of the intrinsic. diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs index ca5aeba86dab9..8e5d55ff3b39a 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -195,7 +195,7 @@ impl IntrinsicType { } } -pub trait IntrinsicTypeDefinition: Deref { +pub trait TypeDefinition: Deref { /// Determines the load function for this type. fn get_load_function(&self) -> String; diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index b577491454e44..78720d6bc5202 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -10,7 +10,7 @@ use crate::common::{ run_rustfmt, write_bin_cargo_toml, write_build_rs, write_lib_cargo_toml, write_lib_rs, }, intrinsic::Intrinsic, - intrinsic_helpers::IntrinsicTypeDefinition, + intrinsic_helpers::TypeDefinition, }; pub mod argument; @@ -29,10 +29,10 @@ pub(crate) const PASSES: u32 = 20; /// Architectures must support this trait /// to be successfully tested. -pub trait SupportedArchitectureTest { - type IntrinsicImpl: IntrinsicTypeDefinition + Sync; +pub trait SupportedArchitecture { + type Type: TypeDefinition + Sync; - fn intrinsics(&self) -> &[Intrinsic]; + fn intrinsics(&self) -> &[Intrinsic]; fn create(cli_options: &ProcessedCli) -> Self; diff --git a/library/stdarch/crates/intrinsic-test/src/common/values.rs b/library/stdarch/crates/intrinsic-test/src/common/values.rs index f7bd4a4eab58d..8c549346ce6ed 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/values.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/values.rs @@ -2,7 +2,7 @@ use itertools::Itertools as _; use crate::common::{ PASSES, - intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, SimdLen, TypeKind}, + intrinsic_helpers::{IntrinsicType, Sign, SimdLen, TypeDefinition, TypeKind}, }; /// Maximum size of a SVE vector @@ -18,7 +18,7 @@ pub const MAX_SVE_BITS: u32 = 2048; /// 0x80, 0x3b, 0xff, /// ]; /// ``` -pub fn test_values_array_static( +pub fn test_values_array_static( w: &mut impl std::io::Write, ty: &T, ) -> std::io::Result<()> { @@ -34,7 +34,7 @@ pub fn test_values_array_static( /// Returns a string with the name of the static variable containing test values for intrinsic /// arguments of this type. -pub fn test_values_array_name(ty: &T) -> String { +pub fn test_values_array_name(ty: &T) -> String { format!( "{ty}_{load_size}", ty = ty.rust_scalar_type().to_uppercase(), diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs index 4c0136041fc35..e25eb48a456d1 100644 --- a/library/stdarch/crates/intrinsic-test/src/main.rs +++ b/library/stdarch/crates/intrinsic-test/src/main.rs @@ -5,10 +5,10 @@ mod arm; mod common; mod x86; -use arm::ArmArchitectureTest; -use common::SupportedArchitectureTest; +use arm::Arm; +use common::SupportedArchitecture; use common::cli::{Cli, ProcessedCli}; -use x86::X86ArchitectureTest; +use x86::X86; fn main() { pretty_env_logger::init(); @@ -18,21 +18,15 @@ fn main() { if processed_cli_options.target.starts_with("arm") | processed_cli_options.target.starts_with("aarch64") { - run( - ArmArchitectureTest::create(&processed_cli_options), - processed_cli_options, - ) + run(Arm::create(&processed_cli_options), processed_cli_options) } else if processed_cli_options.target.starts_with("x86") { - run( - X86ArchitectureTest::create(&processed_cli_options), - processed_cli_options, - ) + run(X86::create(&processed_cli_options), processed_cli_options) } else { unimplemented!("Unsupported target {}", processed_cli_options.target) } } -fn run(test_environment: impl SupportedArchitectureTest, processed_cli_options: ProcessedCli) { +fn run(test_environment: impl SupportedArchitecture, processed_cli_options: ProcessedCli) { info!("building C binaries"); test_environment.generate_c_file(); diff --git a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs index 288bd8bdf8961..ae6d46080982b 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs @@ -4,19 +4,19 @@ mod intrinsic; mod types; mod xml_parser; -use crate::common::SupportedArchitectureTest; +use crate::common::SupportedArchitecture; use crate::common::cli::ProcessedCli; use crate::common::intrinsic::Intrinsic; use crate::common::intrinsic_helpers::TypeKind; use intrinsic::X86IntrinsicType; use xml_parser::get_xml_intrinsics; -pub struct X86ArchitectureTest { +pub struct X86 { intrinsics: Vec>, } -impl SupportedArchitectureTest for X86ArchitectureTest { - type IntrinsicImpl = X86IntrinsicType; +impl SupportedArchitecture for X86 { + type Type = X86IntrinsicType; fn intrinsics(&self) -> &[Intrinsic] { &self.intrinsics diff --git a/library/stdarch/crates/intrinsic-test/src/x86/types.rs b/library/stdarch/crates/intrinsic-test/src/x86/types.rs index a0e14c77d6b5e..b7e063e22804d 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/types.rs @@ -3,12 +3,10 @@ use std::str::FromStr; use itertools::Itertools; use super::intrinsic::X86IntrinsicType; -use crate::common::intrinsic_helpers::{ - IntrinsicType, IntrinsicTypeDefinition, Sign, SimdLen, TypeKind, -}; +use crate::common::intrinsic_helpers::{IntrinsicType, Sign, SimdLen, TypeDefinition, TypeKind}; use crate::x86::xml_parser::Parameter; -impl IntrinsicTypeDefinition for X86IntrinsicType { +impl TypeDefinition for X86IntrinsicType { /// Gets a string containing the type in C format. /// This function assumes that this value is present in the metadata hashmap. fn c_type(&self) -> String { From a7e203ab087688abc2a9ca25340d3eea83471ed4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 2 Jun 2026 13:36:57 +0000 Subject: [PATCH 34/77] intrinsic-test: intrinsic generic over arch not type Refactoring enabling accessing architecture-specific behaviour that isn't associated with either of the return or argument types. --- .../intrinsic-test/src/arm/json_parser.rs | 5 ++-- .../crates/intrinsic-test/src/arm/mod.rs | 5 ++-- .../crates/intrinsic-test/src/common/gen_c.rs | 6 ++--- .../intrinsic-test/src/common/gen_rust.rs | 26 +++++++++---------- .../intrinsic-test/src/common/intrinsic.rs | 12 ++++----- .../crates/intrinsic-test/src/common/mod.rs | 13 +++------- .../crates/intrinsic-test/src/x86/mod.rs | 4 +-- .../intrinsic-test/src/x86/xml_parser.rs | 9 +++---- 8 files changed, 36 insertions(+), 44 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs index ebbde115aa4bf..61e826957d065 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs @@ -1,4 +1,5 @@ use super::intrinsic::ArmType; +use crate::arm::Arm; use crate::arm::types::parse_intrinsic_type; use crate::common::argument::{Argument, ArgumentList}; use crate::common::constraint::Constraint; @@ -59,7 +60,7 @@ struct JsonIntrinsic { pub fn get_neon_intrinsics( filename: &Path, -) -> Result>, Box> { +) -> Result>, Box> { let file = std::fs::File::open(filename)?; let reader = std::io::BufReader::new(file); let json: Vec = serde_json::from_reader(reader).expect("Couldn't parse JSON"); @@ -79,7 +80,7 @@ pub fn get_neon_intrinsics( fn json_to_intrinsic( mut intr: JsonIntrinsic, -) -> Result, Box> { +) -> Result, Box> { let name = intr.name.replace(['[', ']'], ""); let result_ty = ArmType(parse_intrinsic_type(&intr.return_type.value)?); diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 0c5aa5da929de..6cd578fe43d53 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -10,12 +10,13 @@ use crate::common::intrinsic_helpers::{SimdLen, TypeKind}; use intrinsic::ArmType; use json_parser::get_neon_intrinsics; -pub struct Arm(Vec>); +#[derive(PartialEq)] +pub struct Arm(Vec>); impl SupportedArchitecture for Arm { type Type = ArmType; - fn intrinsics(&self) -> &[Intrinsic] { + fn intrinsics(&self) -> &[Intrinsic] { &self.0 } diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index 888f5b2805d08..e4b6c9815c1ea 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -1,6 +1,6 @@ use itertools::Itertools; -use crate::common::intrinsic::Intrinsic; +use crate::common::{SupportedArchitecture, intrinsic::Intrinsic}; use super::intrinsic_helpers::TypeDefinition; @@ -14,11 +14,11 @@ use super::intrinsic_helpers::TypeDefinition; /// *__dst = __crc32cd(a, b); /// } /// ``` -pub fn write_wrapper_c( +pub fn write_wrapper_c( w: &mut impl std::io::Write, notice: &str, platform_headers: &[&str], - intrinsics: &[Intrinsic], + intrinsics: &[Intrinsic], ) -> std::io::Result<()> { write!(w, "{notice}")?; diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index 36f5754367474..a2100e839a645 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -3,11 +3,11 @@ use std::process::Command; use itertools::Itertools; use super::intrinsic_helpers::TypeDefinition; -use crate::common::PASSES; use crate::common::cli::{CcArgStyle, ProcessedCli}; use crate::common::intrinsic::Intrinsic; use crate::common::intrinsic_helpers::TypeKind; use crate::common::values::{test_values_array_name, test_values_array_static}; +use crate::common::{PASSES, SupportedArchitecture}; /// Rust definitions that are included verbatim in the generated source. In particular, defines /// a wrapper around float types that defines `NaN`s to be equal reflexively to enable @@ -98,13 +98,10 @@ cc = "1" /// Writes a Rust source file into `w` with common definitions, static arrays with test values, /// declarations of C wrapper functions for FFI and Rust test functions. -pub fn write_lib_rs( +pub fn write_lib_rs( w: &mut impl std::io::Write, - notice: &str, - cfg: &str, - definitions: &str, i: usize, - intrinsics: &[Intrinsic], + intrinsics: &[Intrinsic], ) -> std::io::Result<()> { writeln!( w, @@ -123,7 +120,10 @@ pub fn write_lib_rs( {COMMON_RUST_DEFINITIONS} {definitions} -"# +"#, + notice = A::NOTICE, + cfg = A::PLATFORM_RUST_CFGS, + definitions = A::PLATFORM_RUST_DEFINITIONS, )?; let mut seen = std::collections::HashSet::new(); @@ -156,9 +156,9 @@ pub fn write_lib_rs( /// (first loop) `PASSES` number of times (second loop). For a given iteration of a given /// specialisation, test values are loaded for each argument and passed to the Rust intrinsic /// and the C wrapper function, and the results are compared. -fn generate_rust_test_loop( +fn generate_rust_test_loop( w: &mut impl std::io::Write, - intrinsic: &Intrinsic, + intrinsic: &Intrinsic, ) -> std::io::Result<()> { let intrinsic_name = &intrinsic.name; @@ -247,9 +247,9 @@ for (id, rust, c) in specializations {{ /// Writes a test function for an given intrinsic to `w`, with a body generated by /// `generate_rust_test_loop`. -fn create_rust_test( +fn create_rust_test( w: &mut impl std::io::Write, - intrinsic: &Intrinsic, + intrinsic: &Intrinsic, ) -> std::io::Result<()> { trace!("generating `{}`", intrinsic.name); @@ -271,10 +271,10 @@ fn test_{intrinsic_name}() {{ /// Writes an `extern "C"` block with function declarations for each of the C wrapper functions into /// `w`. -pub fn write_bindings_rust( +pub fn write_bindings_rust( w: &mut impl std::io::Write, i: usize, - intrinsics: &[Intrinsic], + intrinsics: &[Intrinsic], ) -> std::io::Result<()> { write!( w, diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs index ca59385c3b4e2..904d1d6819f60 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs @@ -1,19 +1,17 @@ -use crate::common::constraint::Constraint; - use super::argument::ArgumentList; -use super::intrinsic_helpers::TypeDefinition; +use crate::common::{SupportedArchitecture, constraint::Constraint}; /// An intrinsic #[derive(Debug, PartialEq, Clone)] -pub struct Intrinsic { +pub struct Intrinsic { /// The function name of this intrinsic. pub name: String, /// Any arguments for this intrinsic. - pub arguments: ArgumentList, + pub arguments: ArgumentList, /// The return type of this intrinsic. - pub results: T, + pub results: A::Type, /// Any architecture-specific tags. pub arch_tags: Vec, @@ -43,7 +41,7 @@ fn recurse_specializations<'a, E>( } } -impl Intrinsic { +impl Intrinsic { /// Invokes `f` for "specialisation" of the intrinsic - a specific instantiation of the /// constant generics of the intrinsic. `f` takes a slice where the `i`th element corresponds /// to the value of the `i`th const generic argument of the intrinsic. diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index 78720d6bc5202..aee2da630a7a4 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -29,10 +29,10 @@ pub(crate) const PASSES: u32 = 20; /// Architectures must support this trait /// to be successfully tested. -pub trait SupportedArchitecture { +pub trait SupportedArchitecture: Sized { type Type: TypeDefinition + Sync; - fn intrinsics(&self) -> &[Intrinsic]; + fn intrinsics(&self) -> &[Intrinsic]; fn create(cli_options: &ProcessedCli) -> Self; @@ -81,14 +81,7 @@ pub trait SupportedArchitecture { trace!("generating `{rust_filename}`"); let mut file = File::create(&rust_filename)?; - write_lib_rs( - &mut file, - Self::NOTICE, - Self::PLATFORM_RUST_CFGS, - Self::PLATFORM_RUST_DEFINITIONS, - i, - chunk, - )?; + write_lib_rs(&mut file, i, chunk)?; run_rustfmt(&rust_filename); let toml_filename = format!("rust_programs/mod_{i}/Cargo.toml"); diff --git a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs index ae6d46080982b..ec198d92188fa 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs @@ -12,13 +12,13 @@ use intrinsic::X86IntrinsicType; use xml_parser::get_xml_intrinsics; pub struct X86 { - intrinsics: Vec>, + intrinsics: Vec>, } impl SupportedArchitecture for X86 { type Type = X86IntrinsicType; - fn intrinsics(&self) -> &[Intrinsic] { + fn intrinsics(&self) -> &[Intrinsic] { &self.intrinsics } diff --git a/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs b/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs index 7815fba2a0a11..f844d749ad32c 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs @@ -1,6 +1,7 @@ use crate::common::argument::{Argument, ArgumentList}; use crate::common::intrinsic::Intrinsic; use crate::common::intrinsic_helpers::TypeKind; +use crate::x86::X86; use crate::x86::constraint::map_constraints; use regex::Regex; @@ -56,13 +57,13 @@ pub struct Parameter { pub fn get_xml_intrinsics( filename: &Path, -) -> Result>, Box> { +) -> Result>, Box> { let file = std::fs::File::open(filename)?; let reader = std::io::BufReader::new(file); let data: Data = quick_xml::de::from_reader(reader).expect("failed to deserialize the source XML file"); - let parsed_intrinsics: Vec> = data + let parsed_intrinsics: Vec> = data .intrinsics .into_iter() .filter(|intrinsic| { @@ -84,9 +85,7 @@ pub fn get_xml_intrinsics( Ok(parsed_intrinsics) } -fn xml_to_intrinsic( - intr: XMLIntrinsic, -) -> Result, Box> { +fn xml_to_intrinsic(intr: XMLIntrinsic) -> Result, Box> { let name = intr.name; let result = X86IntrinsicType::from_param(&intr.return_data); let args_check = intr.parameters.into_iter().enumerate().map(|(i, param)| { From 2a346c542322fc4659dbcfd4300ad15d005bcc03 Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 9 Jun 2026 08:12:08 +0000 Subject: [PATCH 35/77] intrinsic-test: arg generic over arch not type Refactoring enabling accessing architecture-specific behaviour that isn't associated with the specific argument type. --- .../intrinsic-test/src/arm/json_parser.rs | 4 ++-- .../intrinsic-test/src/common/argument.rs | 21 ++++++++++--------- .../intrinsic-test/src/common/intrinsic.rs | 2 +- .../src/common/intrinsic_helpers.rs | 2 +- .../crates/intrinsic-test/src/common/mod.rs | 2 +- .../intrinsic-test/src/x86/xml_parser.rs | 13 ++++-------- 6 files changed, 20 insertions(+), 24 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs index 61e826957d065..26f861ca64b62 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs @@ -122,7 +122,7 @@ fn json_to_intrinsic( }); let mut arg = - Argument::::new(i, String::from(arg_name), ArmType(arg_ty), constraint); + Argument::::new(i, String::from(arg_name), ArmType(arg_ty), constraint); // The JSON doesn't list immediates as const let IntrinsicType { @@ -135,7 +135,7 @@ fn json_to_intrinsic( }) .collect(); - let arguments = ArgumentList:: { args }; + let arguments = ArgumentList:: { args }; Ok(Intrinsic { name, diff --git a/library/stdarch/crates/intrinsic-test/src/common/argument.rs b/library/stdarch/crates/intrinsic-test/src/common/argument.rs index e91a9ab7735e1..0b42151d2862e 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/argument.rs @@ -1,5 +1,6 @@ use itertools::Itertools; +use crate::common::SupportedArchitecture; use crate::common::intrinsic_helpers::TypeKind; use crate::common::values::test_values_array_name; @@ -9,22 +10,22 @@ use super::intrinsic_helpers::TypeDefinition; /// An argument for the intrinsic. #[derive(Debug, PartialEq, Clone)] -pub struct Argument { +pub struct Argument { /// The argument's index in the intrinsic function call. pub pos: usize, /// The argument name. pub name: String, /// The type of the argument. - pub ty: T, + pub ty: A::Type, /// Any constraints that are on this argument pub constraint: Option, } -impl Argument +impl Argument where - T: TypeDefinition, + A: SupportedArchitecture, { - pub fn new(pos: usize, name: String, ty: T, constraint: Option) -> Self { + pub fn new(pos: usize, name: String, ty: A::Type, constraint: Option) -> Self { Argument { pos, name, @@ -63,13 +64,13 @@ where /// Arguments of an intrinsic - including parameters that end up being const generics. #[derive(Debug, PartialEq, Clone)] -pub struct ArgumentList { - pub args: Vec>, +pub struct ArgumentList { + pub args: Vec>, } -impl ArgumentList +impl ArgumentList where - T: TypeDefinition, + A: SupportedArchitecture, { /// Returns a string with the arguments in `self` as a parameter list for a wrapper fn /// definition in C (e.g. `$ty1 $arg1, $ty2 $arg2`). @@ -196,7 +197,7 @@ where } /// Returns an iterator over the contained arguments - pub fn iter(&self) -> std::slice::Iter<'_, Argument> { + pub fn iter(&self) -> std::slice::Iter<'_, Argument> { self.args.iter() } } diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs index 904d1d6819f60..0c5bf43069d00 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs @@ -8,7 +8,7 @@ pub struct Intrinsic { pub name: String, /// Any arguments for this intrinsic. - pub arguments: ArgumentList, + pub arguments: ArgumentList, /// The return type of this intrinsic. pub results: A::Type, diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs index 8e5d55ff3b39a..0e1b699293df9 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -195,7 +195,7 @@ impl IntrinsicType { } } -pub trait TypeDefinition: Deref { +pub trait TypeDefinition: Clone + Deref { /// Determines the load function for this type. fn get_load_function(&self) -> String; diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index aee2da630a7a4..ff0b6cbbafa47 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -30,7 +30,7 @@ pub(crate) const PASSES: u32 = 20; /// Architectures must support this trait /// to be successfully tested. pub trait SupportedArchitecture: Sized { - type Type: TypeDefinition + Sync; + type Type: TypeDefinition + std::fmt::Debug + PartialEq + Sync; fn intrinsics(&self) -> &[Intrinsic]; diff --git a/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs b/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs index f844d749ad32c..52f6da786e3d7 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/xml_parser.rs @@ -99,12 +99,7 @@ fn xml_to_intrinsic(intr: XMLIntrinsic) -> Result, Box::new( - i, - param.var_name.clone(), - ty.unwrap(), - constraint, - ); + let arg = Argument::::new(i, param.var_name.clone(), ty.unwrap(), constraint); Some(arg) } }); @@ -124,8 +119,8 @@ fn xml_to_intrinsic(intr: XMLIntrinsic) -> Result, Box| arg.ty.param.etype.as_str() == "MASK"; - let is_vector = |arg: &Argument| re.is_match(arg.ty.param.type_data.as_str()); + let is_mask = |arg: &Argument| arg.ty.param.etype.as_str() == "MASK"; + let is_vector = |arg: &Argument| re.is_match(arg.ty.param.type_data.as_str()); let pos = args_test.position(|arg| is_mask(arg) && is_vector(arg)); if let Some(index) = pos { args[index].ty.bit_len = args[0].ty.bit_len; @@ -133,7 +128,7 @@ fn xml_to_intrinsic(intr: XMLIntrinsic) -> Result, Box { args }; + let arguments = ArgumentList:: { args }; if let Err(message) = result { return Err(Box::from(message)); From f4b49bc195fb12d8883dd42b045624fac59a7c48 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 11 Jun 2026 09:58:43 +0000 Subject: [PATCH 36/77] intrinsic-test: simplify architecture constants There doesn't need to be so many or other modules with the values. --- .../crates/intrinsic-test/src/arm/config.rs | 25 --- .../crates/intrinsic-test/src/arm/mod.rs | 38 ++++- .../crates/intrinsic-test/src/common/gen_c.rs | 9 +- .../intrinsic-test/src/common/gen_rust.rs | 7 +- .../crates/intrinsic-test/src/common/mod.rs | 12 +- .../crates/intrinsic-test/src/x86/config.rs | 138 ---------------- .../crates/intrinsic-test/src/x86/mod.rs | 148 +++++++++++++++++- 7 files changed, 181 insertions(+), 196 deletions(-) delete mode 100644 library/stdarch/crates/intrinsic-test/src/arm/config.rs delete mode 100644 library/stdarch/crates/intrinsic-test/src/x86/config.rs diff --git a/library/stdarch/crates/intrinsic-test/src/arm/config.rs b/library/stdarch/crates/intrinsic-test/src/arm/config.rs deleted file mode 100644 index 7c26143622e71..0000000000000 --- a/library/stdarch/crates/intrinsic-test/src/arm/config.rs +++ /dev/null @@ -1,25 +0,0 @@ -pub const NOTICE: &str = "\ -// This is a transient test file, not intended for distribution. Some aspects of the -// test are derived from a JSON specification, published under the same license as the -// `intrinsic-test` crate.\n"; - -pub const PLATFORM_RUST_DEFINITIONS: &str = ""; - -pub const PLATFORM_RUST_CFGS: &str = r#" -#![cfg_attr(target_arch = "arm", feature(stdarch_arm_neon_intrinsics))] -#![cfg_attr(target_arch = "arm", feature(stdarch_aarch32_crc32))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_fcma))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_i8mm))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_sm4))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_ftts))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_feat_lut))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_fp8))] -#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(faminmax))] -#![feature(stdarch_neon_f16)] - -#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] -use core_arch::arch::aarch64::*; - -#[cfg(target_arch = "arm")] -use core_arch::arch::arm::*; -"#; diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 6cd578fe43d53..a60e0ff1551a3 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -1,4 +1,3 @@ -mod config; mod intrinsic; mod json_parser; mod types; @@ -20,14 +19,20 @@ impl SupportedArchitecture for Arm { &self.0 } - const NOTICE: &str = config::NOTICE; + const NOTICE: &str = r#" +// This is a transient test file, not intended for distribution. Some aspects of the +// test are derived from a JSON specification, published under the same license as the +// `intrinsic-test` crate. +"#; - const PLATFORM_C_HEADERS: &[&str] = &["arm_neon.h", "arm_acle.h", "arm_fp16.h"]; + const C_PRELUDE: &str = r#" +#include +#include +#include +"#; + const RUST_PRELUDE: &str = RUST_PRELUDE; - const PLATFORM_RUST_DEFINITIONS: &str = config::PLATFORM_RUST_DEFINITIONS; - const PLATFORM_RUST_CFGS: &str = config::PLATFORM_RUST_CFGS; - - fn arch_flags(&self, cli_options: &ProcessedCli) -> Vec<&str> { + fn c_compiler_flags(&self, cli_options: &ProcessedCli) -> Vec<&str> { // GCC uses an extra `-` in the arch name match cli_options.cc_arg_style { CcArgStyle::Clang => vec!["-march=armv8.6a+crypto+crc+dotprod+fp16"], @@ -125,3 +130,22 @@ impl SupportedArchitecture for Arm { Self(intrinsics) } } + +const RUST_PRELUDE: &str = r#" +#![cfg_attr(target_arch = "arm", feature(stdarch_arm_neon_intrinsics))] +#![cfg_attr(target_arch = "arm", feature(stdarch_aarch32_crc32))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_fcma))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_i8mm))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_sm4))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_ftts))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_feat_lut))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_fp8))] +#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(faminmax))] +#![feature(stdarch_neon_f16)] + +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] +use core_arch::arch::aarch64::*; + +#[cfg(target_arch = "arm")] +use core_arch::arch::arm::*; +"#; diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index e4b6c9815c1ea..21cc5cfa2e597 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -16,18 +16,13 @@ use super::intrinsic_helpers::TypeDefinition; /// ``` pub fn write_wrapper_c( w: &mut impl std::io::Write, - notice: &str, - platform_headers: &[&str], intrinsics: &[Intrinsic], ) -> std::io::Result<()> { - write!(w, "{notice}")?; + write!(w, "{}", A::NOTICE)?; writeln!(w, "#include ")?; writeln!(w, "#include ")?; - - for header in platform_headers { - writeln!(w, "#include <{header}>")?; - } + writeln!(w, "{}", A::C_PRELUDE)?; for intrinsic in intrinsics { intrinsic.iter_specializations(|imm_values| { diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index a2100e839a645..432cdde3d45af 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -116,14 +116,11 @@ pub fn write_lib_rs( #![allow(non_camel_case_types)] #![allow(non_snake_case)] -{cfg} +{prelude} {COMMON_RUST_DEFINITIONS} - -{definitions} "#, notice = A::NOTICE, - cfg = A::PLATFORM_RUST_CFGS, - definitions = A::PLATFORM_RUST_DEFINITIONS, + prelude = A::RUST_PRELUDE, )?; let mut seen = std::collections::HashSet::new(); diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index ff0b6cbbafa47..73daabbd6661a 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -38,12 +38,10 @@ pub trait SupportedArchitecture: Sized { const NOTICE: &str; - const PLATFORM_C_HEADERS: &[&str]; + const C_PRELUDE: &str; + const RUST_PRELUDE: &str; - const PLATFORM_RUST_CFGS: &str; - const PLATFORM_RUST_DEFINITIONS: &str; - - fn arch_flags(&self, cli_options: &ProcessedCli) -> Vec<&str>; + fn c_compiler_flags(&self, cli_options: &ProcessedCli) -> Vec<&str>; fn generate_c_file(&self) { let (max_chunk_size, _chunk_count) = manual_chunk(self.intrinsics().len()); @@ -55,14 +53,14 @@ pub trait SupportedArchitecture: Sized { .map(|(i, chunk)| { let c_filename = format!("c_programs/wrapper_{i}.c"); let mut file = File::create(&c_filename).unwrap(); - write_wrapper_c(&mut file, Self::NOTICE, Self::PLATFORM_C_HEADERS, chunk) + write_wrapper_c(&mut file, chunk) }) .collect::>() .unwrap(); } fn generate_rust_file(&self, cli_options: &ProcessedCli) { - let arch_flags = self.arch_flags(cli_options); + let arch_flags = self.c_compiler_flags(cli_options); std::fs::create_dir_all("rust_programs").unwrap(); diff --git a/library/stdarch/crates/intrinsic-test/src/x86/config.rs b/library/stdarch/crates/intrinsic-test/src/x86/config.rs deleted file mode 100644 index 68737ab5ac4c8..0000000000000 --- a/library/stdarch/crates/intrinsic-test/src/x86/config.rs +++ /dev/null @@ -1,138 +0,0 @@ -pub const NOTICE: &str = "\ -// This is a transient test file, not intended for distribution. Some aspects of the -// test are derived from an XML specification, published under the same license as the -// `intrinsic-test` crate.\n"; - -pub const PLATFORM_RUST_DEFINITIONS: &str = r#" -use core_arch::arch::x86_64::*; - -#[inline] -unsafe fn _mm_loadu_ph_to___m128i(mem_addr: *const f16) -> __m128i { - _mm_castph_si128(_mm_loadu_ph(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_ph_to___m256i(mem_addr: *const f16) -> __m256i { - _mm256_castph_si256(_mm256_loadu_ph(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_ph_to___mm512i(mem_addr: *const f16) -> __m512i { - _mm512_castph_si512(_mm512_loadu_ph(mem_addr)) -} - - -#[inline] -unsafe fn _mm_loadu_ps_to___m128h(mem_addr: *const f32) -> __m128h { - _mm_castps_ph(_mm_loadu_ps(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_ps_to___m256h(mem_addr: *const f32) -> __m256h { - _mm256_castps_ph(_mm256_loadu_ps(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_ps_to___m512h(mem_addr: *const f32) -> __m512h { - _mm512_castps_ph(_mm512_loadu_ps(mem_addr)) -} - -#[inline] -unsafe fn _mm_loadu_epi16_to___m128d(mem_addr: *const i16) -> __m128d { - _mm_castsi128_pd(_mm_loadu_epi16(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_epi16_to___m256d(mem_addr: *const i16) -> __m256d { - _mm256_castsi256_pd(_mm256_loadu_epi16(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_epi16_to___m512d(mem_addr: *const i16) -> __m512d { - _mm512_castsi512_pd(_mm512_loadu_epi16(mem_addr)) -} - -#[inline] -unsafe fn _mm_loadu_epi32_to___m128d(mem_addr: *const i32) -> __m128d { - _mm_castsi128_pd(_mm_loadu_epi32(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_epi32_to___m256d(mem_addr: *const i32) -> __m256d { - _mm256_castsi256_pd(_mm256_loadu_epi32(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_epi32_to___m512d(mem_addr: *const i32) -> __m512d { - _mm512_castsi512_pd(_mm512_loadu_epi32(mem_addr)) -} - -#[inline] -unsafe fn _mm_loadu_epi64_to___m128d(mem_addr: *const i64) -> __m128d { - _mm_castsi128_pd(_mm_loadu_epi64(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_epi64_to___m256d(mem_addr: *const i64) -> __m256d { - _mm256_castsi256_pd(_mm256_loadu_epi64(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_epi64_to___m512d(mem_addr: *const i64) -> __m512d { - _mm512_castsi512_pd(_mm512_loadu_epi64(mem_addr)) -} - -// === -#[inline] -unsafe fn _mm_loadu_epi16_to___m128(mem_addr: *const i16) -> __m128 { - _mm_castsi128_ps(_mm_loadu_epi16(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_epi16_to___m256(mem_addr: *const i16) -> __m256 { - _mm256_castsi256_ps(_mm256_loadu_epi16(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_epi16_to___m512(mem_addr: *const i16) -> __m512 { - _mm512_castsi512_ps(_mm512_loadu_epi16(mem_addr)) -} - -#[inline] -unsafe fn _mm_loadu_epi32_to___m128(mem_addr: *const i32) -> __m128 { - _mm_castsi128_ps(_mm_loadu_epi32(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_epi32_to___m256(mem_addr: *const i32) -> __m256 { - _mm256_castsi256_ps(_mm256_loadu_epi32(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_epi32_to___m512(mem_addr: *const i32) -> __m512 { - _mm512_castsi512_ps(_mm512_loadu_epi32(mem_addr)) -} - -#[inline] -unsafe fn _mm_loadu_epi64_to___m128(mem_addr: *const i64) -> __m128 { - _mm_castsi128_ps(_mm_loadu_epi64(mem_addr)) -} - -#[inline] -unsafe fn _mm256_loadu_epi64_to___m256(mem_addr: *const i64) -> __m256 { - _mm256_castsi256_ps(_mm256_loadu_epi64(mem_addr)) -} - -#[inline] -unsafe fn _mm512_loadu_epi64_to___m512(mem_addr: *const i64) -> __m512 { - _mm512_castsi512_ps(_mm512_loadu_epi64(mem_addr)) -} - -"#; - -pub const PLATFORM_RUST_CFGS: &str = r#" -#![feature(stdarch_x86_avx512_bf16)] -#![feature(stdarch_x86_avx512_f16)] -#![feature(stdarch_x86_rtm)] -#![feature(x86_amx_intrinsics)] -"#; diff --git a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs index ec198d92188fa..ce4955032916d 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs @@ -1,4 +1,3 @@ -mod config; mod constraint; mod intrinsic; mod types; @@ -22,14 +21,18 @@ impl SupportedArchitecture for X86 { &self.intrinsics } - const NOTICE: &str = config::NOTICE; + const NOTICE: &str = r#" +// This is a transient test file, not intended for distribution. Some aspects of the +// test are derived from an XML specification, published under the same license as the +// `intrinsic-test` crate. +"#; - const PLATFORM_C_HEADERS: &[&str] = &["immintrin.h"]; + const C_PRELUDE: &str = r#" +#include +"#; + const RUST_PRELUDE: &str = RUST_PRELUDE; - const PLATFORM_RUST_DEFINITIONS: &str = config::PLATFORM_RUST_DEFINITIONS; - const PLATFORM_RUST_CFGS: &str = config::PLATFORM_RUST_CFGS; - - fn arch_flags(&self, _cli_options: &ProcessedCli) -> Vec<&str> { + fn c_compiler_flags(&self, _cli_options: &ProcessedCli) -> Vec<&str> { vec![ "-maes", "-mf16c", @@ -97,3 +100,134 @@ impl SupportedArchitecture for X86 { Self { intrinsics } } } + +const RUST_PRELUDE: &str = r#" +#![feature(stdarch_x86_avx512_bf16)] +#![feature(stdarch_x86_avx512_f16)] +#![feature(stdarch_x86_rtm)] +#![feature(x86_amx_intrinsics)] + +use core_arch::arch::x86_64::*; + +#[inline] +unsafe fn _mm_loadu_ph_to___m128i(mem_addr: *const f16) -> __m128i { + _mm_castph_si128(_mm_loadu_ph(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_ph_to___m256i(mem_addr: *const f16) -> __m256i { + _mm256_castph_si256(_mm256_loadu_ph(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_ph_to___mm512i(mem_addr: *const f16) -> __m512i { + _mm512_castph_si512(_mm512_loadu_ph(mem_addr)) +} + + +#[inline] +unsafe fn _mm_loadu_ps_to___m128h(mem_addr: *const f32) -> __m128h { + _mm_castps_ph(_mm_loadu_ps(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_ps_to___m256h(mem_addr: *const f32) -> __m256h { + _mm256_castps_ph(_mm256_loadu_ps(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_ps_to___m512h(mem_addr: *const f32) -> __m512h { + _mm512_castps_ph(_mm512_loadu_ps(mem_addr)) +} + +#[inline] +unsafe fn _mm_loadu_epi16_to___m128d(mem_addr: *const i16) -> __m128d { + _mm_castsi128_pd(_mm_loadu_epi16(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_epi16_to___m256d(mem_addr: *const i16) -> __m256d { + _mm256_castsi256_pd(_mm256_loadu_epi16(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_epi16_to___m512d(mem_addr: *const i16) -> __m512d { + _mm512_castsi512_pd(_mm512_loadu_epi16(mem_addr)) +} + +#[inline] +unsafe fn _mm_loadu_epi32_to___m128d(mem_addr: *const i32) -> __m128d { + _mm_castsi128_pd(_mm_loadu_epi32(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_epi32_to___m256d(mem_addr: *const i32) -> __m256d { + _mm256_castsi256_pd(_mm256_loadu_epi32(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_epi32_to___m512d(mem_addr: *const i32) -> __m512d { + _mm512_castsi512_pd(_mm512_loadu_epi32(mem_addr)) +} + +#[inline] +unsafe fn _mm_loadu_epi64_to___m128d(mem_addr: *const i64) -> __m128d { + _mm_castsi128_pd(_mm_loadu_epi64(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_epi64_to___m256d(mem_addr: *const i64) -> __m256d { + _mm256_castsi256_pd(_mm256_loadu_epi64(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_epi64_to___m512d(mem_addr: *const i64) -> __m512d { + _mm512_castsi512_pd(_mm512_loadu_epi64(mem_addr)) +} + +// === +#[inline] +unsafe fn _mm_loadu_epi16_to___m128(mem_addr: *const i16) -> __m128 { + _mm_castsi128_ps(_mm_loadu_epi16(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_epi16_to___m256(mem_addr: *const i16) -> __m256 { + _mm256_castsi256_ps(_mm256_loadu_epi16(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_epi16_to___m512(mem_addr: *const i16) -> __m512 { + _mm512_castsi512_ps(_mm512_loadu_epi16(mem_addr)) +} + +#[inline] +unsafe fn _mm_loadu_epi32_to___m128(mem_addr: *const i32) -> __m128 { + _mm_castsi128_ps(_mm_loadu_epi32(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_epi32_to___m256(mem_addr: *const i32) -> __m256 { + _mm256_castsi256_ps(_mm256_loadu_epi32(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_epi32_to___m512(mem_addr: *const i32) -> __m512 { + _mm512_castsi512_ps(_mm512_loadu_epi32(mem_addr)) +} + +#[inline] +unsafe fn _mm_loadu_epi64_to___m128(mem_addr: *const i64) -> __m128 { + _mm_castsi128_ps(_mm_loadu_epi64(mem_addr)) +} + +#[inline] +unsafe fn _mm256_loadu_epi64_to___m256(mem_addr: *const i64) -> __m256 { + _mm256_castsi256_ps(_mm256_loadu_epi64(mem_addr)) +} + +#[inline] +unsafe fn _mm512_loadu_epi64_to___m512(mem_addr: *const i64) -> __m512 { + _mm512_castsi512_ps(_mm512_loadu_epi64(mem_addr)) +} +"#; From 62ddde1d17c469813a045a0c97a4c6acea6fd8d9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 1 Jun 2026 12:44:41 +0000 Subject: [PATCH 37/77] intrinsic-test: simplify type printing A small refactoring to make the type printing logic slightly cleaner and with greater code re-use. --- .../crates/intrinsic-test/src/arm/types.rs | 80 ++++++++++++------- .../src/common/intrinsic_helpers.rs | 25 +++--- 2 files changed, 64 insertions(+), 41 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/types.rs b/library/stdarch/crates/intrinsic-test/src/arm/types.rs index 44af107eb96e5..d27ae8069152c 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/types.rs @@ -6,21 +6,32 @@ impl TypeDefinition for ArmType { fn c_type(&self) -> String { let prefix = self.kind.c_prefix(); - if let Some(bit_len) = self.bit_len { - match (self.simd_len, self.vec_len) { - (None, None) => format!("{prefix}{bit_len}_t"), - (Some(SimdLen::Fixed(simd)), None) => format!("{prefix}{bit_len}x{simd}_t"), - (Some(SimdLen::Fixed(simd)), Some(vec)) => { - format!("{prefix}{bit_len}x{simd}x{vec}_t") - } - (Some(SimdLen::Scalable), None) => format!("sv{prefix}{bit_len}_t"), - (Some(SimdLen::Scalable), Some(vec)) => { - format!("sv{prefix}{bit_len}x{vec}_t") - } - (None, Some(_)) => todo!("{self:#?}"), // Likely an invalid case + match (self.bit_len, self.simd_len, self.vec_len) { + // e.g. `bool` + (Some(_), None, None) if matches!(self.kind, TypeKind::Bool) => { + format!("{prefix}") } - } else { - todo!("{self:#?}") + // e.g. `float32_t`, `int64_t` + (Some(bit_len), None, None) => format!("{prefix}{bit_len}_t"), + // e.g. `float32x2_t`, `int64x2_t` + (Some(bit_len), Some(SimdLen::Fixed(simd)), None) => { + format!("{prefix}{bit_len}x{simd}_t") + } + // e.g. `float32x2x3_t`, `int64x2x3_t` + (Some(bit_len), Some(SimdLen::Fixed(simd)), Some(vec)) => { + format!("{prefix}{bit_len}x{simd}x{vec}_t") + } + // e.g. `svbool_t` + (Some(_), Some(SimdLen::Scalable), None) if matches!(self.kind, TypeKind::Bool) => { + format!("sv{prefix}_t") + } + // e.g. `svfloat32_t`, `svint64_t` + (Some(bit_len), Some(SimdLen::Scalable), None) => format!("sv{prefix}{bit_len}_t"), + // e.g. `svfloat32x3_t`, `svint64x3_t` + (Some(bit_len), Some(SimdLen::Scalable), Some(vec)) => { + format!("sv{prefix}{bit_len}x{vec}_t") + } + _ => todo!("{self:#?}"), } } @@ -28,21 +39,34 @@ impl TypeDefinition for ArmType { let rust_prefix = self.kind.rust_prefix(); let c_prefix = self.kind.c_prefix(); - if let Some(bit_len) = self.bit_len { - match (self.simd_len, self.vec_len) { - (None, None) => format!("{rust_prefix}{bit_len}"), - (Some(SimdLen::Fixed(simd)), None) => format!("{c_prefix}{bit_len}x{simd}_t"), - (Some(SimdLen::Fixed(simd)), Some(vec)) => { - format!("{c_prefix}{bit_len}x{simd}x{vec}_t") - } - (Some(SimdLen::Scalable), None) => format!("sv{c_prefix}{bit_len}_t"), - (Some(SimdLen::Scalable), Some(vec)) => { - format!("sv{c_prefix}{bit_len}x{vec}_t") - } - (None, Some(_)) => todo!("{self:#?}"), // Likely an invalid case + match (self.bit_len, self.simd_len, self.vec_len) { + // e.g. `svpattern` + (None, _, _) => format!("{rust_prefix}"), + // e.g. `bool` + (Some(_), None, None) if matches!(self.kind, TypeKind::Bool) => { + format!("{rust_prefix}") } - } else { - todo!("{self:#?}") + // e.g. `i32` + (Some(bit_len), None, None) => format!("{rust_prefix}{bit_len}"), + // e.g. `int32x2_t` + (Some(bit_len), Some(SimdLen::Fixed(simd)), None) => { + format!("{c_prefix}{bit_len}x{simd}_t") + } + // e.g. `int32x2x3_t` + (Some(bit_len), Some(SimdLen::Fixed(simd)), Some(vec)) => { + format!("{c_prefix}{bit_len}x{simd}x{vec}_t") + } + // e.g. `svbool_t` + (Some(_), Some(SimdLen::Scalable), None) if matches!(self.kind, TypeKind::Bool) => { + format!("sv{c_prefix}_t") + } + // e.g. `svint32_t` + (Some(bit_len), Some(SimdLen::Scalable), None) => format!("sv{c_prefix}{bit_len}_t"), + // e.g. `svint32x3_t` + (Some(bit_len), Some(SimdLen::Scalable), Some(vec)) => { + format!("sv{c_prefix}{bit_len}x{vec}_t") + } + (Some(_), None, Some(_)) => todo!("{self:#?}"), } } diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs index 0e1b699293df9..aae4a594df935 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -1,6 +1,6 @@ use std::cmp; use std::fmt; -use std::ops::Deref; +use std::ops::DerefMut; use std::str::FromStr; #[derive(Debug, PartialEq, Copy, Clone)] @@ -90,9 +90,13 @@ impl TypeKind { } } - /// Returns the Rust prefix for this type kind i.e. `i`, `u`, or `f`. + /// Returns the Rust prefix for this type kind (i.e. `i` for `i16`, or `u` for `u16`). For type + /// kinds without any bit length at the end (e.g. `bool`), returns the whole type name. pub fn rust_prefix(&self) -> &str { match self { + Self::Bool => "bool", + Self::SvPattern => "svpattern", + Self::SvPrefetchOp => "svprfop", Self::BFloat => "bf", Self::Float => "f", Self::Int(Sign::Signed) => "i", @@ -101,7 +105,7 @@ impl TypeKind { Self::Char(Sign::Unsigned) => "u", Self::Char(Sign::Signed) => "i", Self::Mask => "u", - _ => unreachable!("Unused type kind: {self:#?}"), + _ => unreachable!("type kind without Rust prefix: {self:#?}"), } } } @@ -195,7 +199,7 @@ impl IntrinsicType { } } -pub trait TypeDefinition: Clone + Deref { +pub trait TypeDefinition: Clone + DerefMut { /// Determines the load function for this type. fn get_load_function(&self) -> String; @@ -208,14 +212,9 @@ pub trait TypeDefinition: Clone + Deref { /// Gets a string containing the name of the scalar type corresponding to this type if it is a /// vector. fn rust_scalar_type(&self) -> String { - if self.is_simd() { - format!( - "{prefix}{bits}", - prefix = self.kind().rust_prefix(), - bits = self.inner_size() - ) - } else { - self.rust_type() - } + let mut ty = self.clone(); + ty.simd_len = None; + ty.vec_len = None; + ty.rust_type() } } From bae77b10221c92aa5d4f1e79a4b72d1c0c82f236 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 1 Jun 2026 12:44:41 +0000 Subject: [PATCH 38/77] intrinsic-test: introduce `get_comparison_function` Introduces a per-architecture abstraction over how intrinsic results are compared, so that later commits can implement Arm-specific comparison logic for SVE. --- .../intrinsic-test/src/common/gen_rust.rs | 27 +--------- .../src/common/intrinsic_helpers.rs | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index 432cdde3d45af..f6a7c62a3cbd5 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -5,7 +5,6 @@ use itertools::Itertools; use super::intrinsic_helpers::TypeDefinition; use crate::common::cli::{CcArgStyle, ProcessedCli}; use crate::common::intrinsic::Intrinsic; -use crate::common::intrinsic_helpers::TypeKind; use crate::common::values::{test_values_array_name, test_values_array_static}; use crate::common::{PASSES, SupportedArchitecture}; @@ -195,29 +194,6 @@ fn generate_rust_test_loop( writeln!(w, " ];")?; } - let (cast_prefix, cast_suffix) = if intrinsic.results.is_simd() { - ( - format!( - "std::mem::transmute::<_, [{}; {}]>(", - intrinsic.results.rust_scalar_type().replace("f", "NanEqF"), - intrinsic.results.num_lanes() * intrinsic.results.num_vectors() - ), - ")", - ) - } else if intrinsic.results.kind == TypeKind::Float { - ( - match intrinsic.results.inner_size() { - 16 => format!("NanEqF16("), - 32 => format!("NanEqF32("), - 64 => format!("NanEqF64("), - _ => unimplemented!(), - }, - ")", - ) - } else { - ("".to_string(), "") - }; - write!( w, r#" @@ -231,7 +207,7 @@ for (id, rust, c) in specializations {{ c(__c_return_value.as_mut_ptr(){c_args}); let __c_return_value = __c_return_value.assume_init(); - assert_eq!({cast_prefix}__rust_return_value{cast_suffix}, {cast_prefix}__c_return_value{cast_suffix}, "{{id}}"); + {comparison} }} }} }} @@ -239,6 +215,7 @@ for (id, rust, c) in specializations {{ loaded_args = intrinsic.arguments.load_values_rust(), rust_args = intrinsic.arguments.as_call_param_rust(), c_args = intrinsic.arguments.as_c_call_param_rust(), + comparison = intrinsic.results.get_comparison_function(), ) } diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs index aae4a594df935..18ab3b745d513 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -203,6 +203,16 @@ pub trait TypeDefinition: Clone + DerefMut { /// Determines the load function for this type. fn get_load_function(&self) -> String; + /// Determines the comparison function for this type. + fn get_comparison_function(&self) -> String { + match self.simd_len { + Some(SimdLen::Scalable) => unimplemented!("architecture-specific"), + Some(SimdLen::Fixed(_)) | None => { + default_fixed_vector_comparison(self, self.num_lanes()) + } + } + } + /// Gets a string containing the typename for this type in C. fn c_type(&self) -> String; @@ -218,3 +228,43 @@ pub trait TypeDefinition: Clone + DerefMut { ty.rust_type() } } + +/// Returns the default comparison between results of an intrinsic - casting the vectors to arrays +/// and using `assert_eq` - using `NanEqF*` where required for floats. +pub(crate) fn default_fixed_vector_comparison( + ty: &Ty, + num_lanes: u32, +) -> String { + let (cast_prefix, cast_suffix) = if ty.is_simd() { + ( + format!( + "std::mem::transmute::<_, [{}; {}]>(", + ty.rust_scalar_type().replace("f", "NanEqF"), + num_lanes * ty.num_vectors() + ), + ")", + ) + } else if ty.kind == TypeKind::Float { + ( + match ty.inner_size() { + 16 => format!("NanEqF16("), + 32 => format!("NanEqF32("), + 64 => format!("NanEqF64("), + _ => unimplemented!(), + }, + ")", + ) + } else { + ("".to_string(), "") + }; + + format!( + r#" +assert_eq!( + {cast_prefix}__rust_return_value{cast_suffix}, + {cast_prefix}__c_return_value{cast_suffix}, + "{{id}}" +); +"#, + ) +} From 9686cccca9aee46a33283beb5fa744c162518a86 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 4 Jun 2026 12:48:11 +0000 Subject: [PATCH 39/77] intrinsic-test: rename `get_*_function` fns --- library/stdarch/crates/intrinsic-test/src/arm/types.rs | 4 ++-- library/stdarch/crates/intrinsic-test/src/common/argument.rs | 2 +- library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs | 2 +- .../crates/intrinsic-test/src/common/intrinsic_helpers.rs | 4 ++-- library/stdarch/crates/intrinsic-test/src/x86/types.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/types.rs b/library/stdarch/crates/intrinsic-test/src/arm/types.rs index d27ae8069152c..7754e9ec2d0dd 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/types.rs @@ -71,7 +71,7 @@ impl TypeDefinition for ArmType { } /// Determines the load function for this type. - fn get_load_function(&self) -> String { + fn load_function(&self) -> String { if let IntrinsicType { kind: k, bit_len: Some(bl), @@ -95,7 +95,7 @@ impl TypeDefinition for ArmType { len = vec_len.unwrap_or(1), ) } else { - todo!("get_load_function IntrinsicType: {self:#?}") + todo!("load_function IntrinsicType: {self:#?}") } } } diff --git a/library/stdarch/crates/intrinsic-test/src/common/argument.rs b/library/stdarch/crates/intrinsic-test/src/common/argument.rs index 0b42151d2862e..4d38bce327930 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/argument.rs @@ -183,7 +183,7 @@ where "let {name} = {load}({vals_name}.as_ptr().add((i+{idx}) % {PASSES}) as _);", name = arg.generate_name(), vals_name = test_values_array_name(&arg.ty), - load = arg.ty.get_load_function(), + load = arg.ty.load_function(), ) } else { format!( diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index f6a7c62a3cbd5..baa11511ec219 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -215,7 +215,7 @@ for (id, rust, c) in specializations {{ loaded_args = intrinsic.arguments.load_values_rust(), rust_args = intrinsic.arguments.as_call_param_rust(), c_args = intrinsic.arguments.as_c_call_param_rust(), - comparison = intrinsic.results.get_comparison_function(), + comparison = intrinsic.results.comparison_function(), ) } diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs index 18ab3b745d513..b9f30af7dfd51 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -201,10 +201,10 @@ impl IntrinsicType { pub trait TypeDefinition: Clone + DerefMut { /// Determines the load function for this type. - fn get_load_function(&self) -> String; + fn load_function(&self) -> String; /// Determines the comparison function for this type. - fn get_comparison_function(&self) -> String { + fn comparison_function(&self) -> String { match self.simd_len { Some(SimdLen::Scalable) => unimplemented!("architecture-specific"), Some(SimdLen::Fixed(_)) | None => { diff --git a/library/stdarch/crates/intrinsic-test/src/x86/types.rs b/library/stdarch/crates/intrinsic-test/src/x86/types.rs index b7e063e22804d..2cba54a73f767 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/types.rs @@ -48,7 +48,7 @@ impl TypeDefinition for X86IntrinsicType { } /// Determines the load function for this type. - fn get_load_function(&self) -> String { + fn load_function(&self) -> String { let type_value = self.param.type_data.clone(); if type_value.len() == 0 { unimplemented!("the value for key 'type' is not present!"); From cc45b69ee5f66a560c88a92fe588aa5d88a34be6 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Mon, 22 Jun 2026 06:12:25 +0000 Subject: [PATCH 40/77] Prepare for merging from rust-lang/rust This updates the rust-version file to 942ac9ce4116d4ea784c9882659372b34978b1f8. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 4a2bfdb2cd558..5db47ca8fc59b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -01f54e80e888b66d6486a3a95d481b87353016df +942ac9ce4116d4ea784c9882659372b34978b1f8 From b973eb94a52630da5606b44272b89198f60968cc Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Mon, 22 Jun 2026 19:02:02 +0100 Subject: [PATCH 41/77] Allow unstable attribute on foreign types and add stability test --- compiler/rustc_attr_parsing/src/attributes/stability.rs | 1 + tests/ui/lint/lint-stability.rs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index b38bb6d535770..734acb9ea21e7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -40,6 +40,7 @@ const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Static), Allow(Target::ForeignFn), Allow(Target::ForeignStatic), + Allow(Target::ForeignTy), Allow(Target::ExternCrate), ]); diff --git a/tests/ui/lint/lint-stability.rs b/tests/ui/lint/lint-stability.rs index f080b5e4bbeb1..21009b1e61db4 100644 --- a/tests/ui/lint/lint-stability.rs +++ b/tests/ui/lint/lint-stability.rs @@ -6,9 +6,13 @@ #![allow(deprecated)] #![allow(dead_code)] #![feature(staged_api)] - +#![feature(extern_types)] #![stable(feature = "rust1", since = "1.0.0")] +extern "C" { + #[unstable(feature = "fn_static", issue = "none")] + type Ty; +} #[macro_use] extern crate lint_stability; From 8d2cf93085c8593be84112237c4186f7d581a4ba Mon Sep 17 00:00:00 2001 From: Ed Swartz <875407+eswartz@users.noreply.github.com> Date: Wed, 17 Jun 2026 20:35:23 -0500 Subject: [PATCH 42/77] Update `cargo miri --help` to point to README.md. --- src/tools/miri/cargo-miri/src/phases.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index f58cec827cf5d..4a41c4997cac5 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -36,6 +36,9 @@ Examples: This will print the path to the generated sysroot (and nothing else) on stdout. stderr will still contain progress information about how the build is doing. +For documentation on `-Zmiri-...` flags, see miri's local README.md +(for example, $(rustc --print sysroot)/share/doc/miri/README.md) +or the rendered version at [https://github.com/rust-lang/miri/blob/master/README.md]. "; fn show_help() { From aa5792a9e7bc75f13cdb2895cc3947b93548a830 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 23 Jun 2026 19:59:01 +0200 Subject: [PATCH 43/77] reformat pointers to README --- src/tools/miri/cargo-miri/src/phases.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 4a41c4997cac5..caf6987291970 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -36,9 +36,9 @@ Examples: This will print the path to the generated sysroot (and nothing else) on stdout. stderr will still contain progress information about how the build is doing. -For documentation on `-Zmiri-...` flags, see miri's local README.md -(for example, $(rustc --print sysroot)/share/doc/miri/README.md) -or the rendered version at [https://github.com/rust-lang/miri/blob/master/README.md]. +For documentation on `-Zmiri-...` flags, see Miri's README.md, available at: +- $(rustc --print sysroot)/share/doc/miri/README.md +- https://github.com/rust-lang/miri/blob/master/README.md "; fn show_help() { From 0cf893ebe23bb181cd9949e22f0ae3007d0018f1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jun 2026 17:24:42 +0200 Subject: [PATCH 44/77] dont ICE on generic no_mangle items --- src/tools/miri/src/helpers.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 730c7d9fac611..9a601265defb9 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -129,7 +129,13 @@ pub fn iter_exported_symbols<'tcx>( || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) }; - if exported { + // FIXME: `#[no_mangle]` makes no sense on a generic item, but still causes it to be + // considered "extern". Remove this once `no_mangle_generic_items` is a hard error. + let exported_mono = exported && { + let generics = tcx.generics_of(def_id); + !generics.requires_monomorphization(tcx) + }; + if exported_mono { f(LOCAL_CRATE, def_id.into())?; } } From dc5b1a958e4fd5b5fe5c4ba1b062143272792011 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jun 2026 17:30:07 +0200 Subject: [PATCH 45/77] test-cargo-miri: test all workspace members --- src/tools/miri/test-cargo-miri/run-test.py | 7 +- .../test.proc-macro.stdout.ref | 5 - ...o.stderr.ref => test.workspace.stderr.ref} | 0 .../test-cargo-miri/test.workspace.stdout.ref | 103 ++++++++++++++++++ 4 files changed, 107 insertions(+), 8 deletions(-) delete mode 100644 src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref rename src/tools/miri/test-cargo-miri/{test.proc-macro.stderr.ref => test.workspace.stderr.ref} (100%) create mode 100644 src/tools/miri/test-cargo-miri/test.workspace.stdout.ref diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index cfbe3098e54ff..afebdff51157d 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -170,9 +170,10 @@ def test_cargo_miri_test(): "test.empty.ref", env={'MIRIFLAGS': "-Zmiri-disable-isolation"}, ) - test("`cargo miri test` (proc-macro crate)", - cargo_miri("test") + ["-p", "proc_macro_crate"], - "test.proc-macro.stdout.ref", "test.proc-macro.stderr.ref", + test("`cargo miri test` (entire workspace, no isolation)", + cargo_miri("test") + ["--workspace"], + "test.workspace.stdout.ref", "test.workspace.stderr.ref", + env={'MIRIFLAGS': "-Zmiri-disable-isolation"}, ) test("`cargo miri test` (custom target dir)", cargo_miri("test") + ["--target-dir=custom-test"], diff --git a/src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref b/src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref deleted file mode 100644 index 7326c0a25a069..0000000000000 --- a/src/tools/miri/test-cargo-miri/test.proc-macro.stdout.ref +++ /dev/null @@ -1,5 +0,0 @@ - -running 0 tests - -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME - diff --git a/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref b/src/tools/miri/test-cargo-miri/test.workspace.stderr.ref similarity index 100% rename from src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref rename to src/tools/miri/test-cargo-miri/test.workspace.stderr.ref diff --git a/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref b/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref new file mode 100644 index 0000000000000..a4e224a329797 --- /dev/null +++ b/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref @@ -0,0 +1,103 @@ + +running 2 tests +.. +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + +imported main + +running 6 tests +...i.. +test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + +subcrate testing + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 5 tests +..... +test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + +all doctests ran in $TIME; merged doctests compilation took $TIME + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 1 test +. +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 01a12a403fc64eb7e47ed7ec4d8883e221bc1206 Mon Sep 17 00:00:00 2001 From: Cai Congcong Date: Sun, 29 Mar 2026 22:17:10 +0800 Subject: [PATCH 46/77] add ui test for no mangle generic --- .../tests/pass/issues/issue-154385-no-mangle-generic.rs | 9 +++++++++ .../pass/issues/issue-154385-no-mangle-generic.stdout | 1 + 2 files changed, 10 insertions(+) create mode 100644 src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs create mode 100644 src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout diff --git a/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs b/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs new file mode 100644 index 0000000000000..0989cdd86a362 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.rs @@ -0,0 +1,9 @@ +fn main() { + foo(1234); +} + +#[allow(no_mangle_generic_items)] +#[unsafe(no_mangle)] +fn foo(value: T) { + println!("{value:?}"); +} diff --git a/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout b/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout new file mode 100644 index 0000000000000..81c545efebe5f --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-154385-no-mangle-generic.stdout @@ -0,0 +1 @@ +1234 From eca4b5b83d60c97247c41846aec6a215d33794ae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jun 2026 14:00:22 +0200 Subject: [PATCH 47/77] move nextest section up and mark it more clearly as such --- src/tools/miri/README.md | 53 +++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 6b8d8ed1f8018..fdc746ead51f5 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -171,6 +171,38 @@ available (which affects `cfg(target_feature)`), and it tells Miri to consider t that the interpreted program runs on as having the feature available (meaning the code is allowed to invoke the corresponding intrinsics). +### Nextest integration + +Miri can be combined with [`cargo-nextest`](https://nexte.st): + +``` +cargo install --locked cargo-nextest +cargo miri nextest run +``` + +Nextest spawns a separate instance of Miri for each test, which has several advantages: +- Tests can run in parallel. Miri itself only uses a single thread per interpreter so this can + give a massive speedup (but see the caveat below). +- Tests do not stop when a single problem is found. Miri aborts execution when it encounters + Undefined Behavior or an unsupported operation (there is often not really any way to continue), + so once a single test fails, the remaining tests cannot be executed. Nextest's process-per-test + model means that you end up with a full list of which tests worked in Miri and which tests had a + problem. + +However, there is also a big caveat: Miri will [re-compile the test crate every time it is +invoked](https://github.com/rust-lang/miri/issues/5013), which means a crate with N tests will be +compiled N+1 times. If the test crate takes a long time to build, this can outweigh the benefits of +parallelization. + +For more information about nextest, see the [`cargo-nextest` Miri +documentation](https://nexte.st/book/miri.html). + +Note: Nextest's one-test-per-process model means that `cargo miri test` is able to detect data +races where two tests race on a shared resource, but `cargo miri nextest run` will not detect +such races. + +Note: `cargo-nextest` [does not support doctests](https://github.com/nextest-rs/nextest/issues/16). + ### Testing multiple different executions Certain parts of the execution are picked randomly by Miri, such as the exact base address @@ -184,6 +216,7 @@ MIRIFLAGS="-Zmiri-many-seeds" cargo miri test # tries the seeds in 0..64 MIRIFLAGS="-Zmiri-many-seeds=0..16" cargo miri test ``` +Miri will test the given range of seeds with parallel interpreter instances. The default of 64 different seeds can be quite slow, so you often want to specify a smaller range. ### Running Miri on CI @@ -243,26 +276,6 @@ However, even for targets that we do support, the degree of support for accessin (such as the file system) differs between targets: generally, Linux targets have the best support, and macOS targets are usually on par. Windows is supported less well. -### Running tests in parallel - -Though it implements Rust threading, Miri itself is a single-threaded interpreter -(it works like a multi-threaded OS on a single-core CPU). -This means that when running `cargo miri test`, you will probably see a dramatic -increase in the amount of time it takes to run your whole test suite due to the -inherent interpreter slowdown and a loss of parallelism. - -You can get your test suite's parallelism back by running `cargo miri nextest run -jN` -(note that you will need [`cargo-nextest`](https://nexte.st) installed). -This works because `cargo-nextest` collects a list of all tests then launches a -separate `cargo miri run` for each test. For more information about nextest, see the -[`cargo-nextest` Miri documentation](https://nexte.st/book/miri.html). - -Note: This one-test-per-process model means that `cargo miri test` is able to detect data -races where two tests race on a shared resource, but `cargo miri nextest run` will not detect -such races. - -Note: `cargo-nextest` does not support doctests, see https://github.com/nextest-rs/nextest/issues/16 - ### Directly invoking the `miri` driver The recommended way to invoke Miri is via `cargo miri`. Directly invoking the underlying `miri` From 233759097cf498c6cd441cb4529c7b984d256044 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jun 2026 14:17:44 +0200 Subject: [PATCH 48/77] add some more errno_result --- .../fail-dep/libc/eventfd_block_read_twice.rs | 6 +++++- .../libc/eventfd_block_write_twice.rs | 6 +++++- .../fail-dep/libc/libc-epoll-data-race.rs | 3 +-- .../libc/libc_epoll_block_two_thread.rs | 8 ++++---- .../libc/libc_epoll_unsupported_fd.rs | 10 ++++++---- .../pass-dep/libc/libc-epoll-no-blocking.rs | 20 +++++++------------ .../miri/tests/pass-dep/libc/libc-eventfd.rs | 19 +++++++++--------- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 2 +- .../libc/libc-socket-no-blocking-epoll.rs | 6 +++--- 9 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs index 98cc80b6b4ea2..d4d14d449aa68 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs @@ -4,6 +4,10 @@ use std::thread; +#[path = "../../utils/libc.rs"] +mod libc_utils; +use libc_utils::*; + // Test the behaviour of a thread being blocked on an eventfd read, get unblocked, and then // get blocked again. @@ -18,7 +22,7 @@ fn main() { // eventfd write will block when EFD_NONBLOCK flag is clear // and the addition caused counter to exceed u64::MAX - 1. let flags = libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); let thread1 = thread::spawn(move || { let mut buf: [u8; 8] = [0; 8]; diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs index 1a1d76eda2003..39d00a7522761 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs @@ -4,6 +4,10 @@ use std::thread; +#[path = "../../utils/libc.rs"] +mod libc_utils; +use libc_utils::*; + // Test the behaviour of a thread being blocked on an eventfd `write`, get unblocked, and then // get blocked again. @@ -17,7 +21,7 @@ fn main() { // eventfd write will block when EFD_NONBLOCK flag is clear // and the addition caused counter to exceed u64::MAX - 1. let flags = libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + let fd = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); // Write u64 - 1, so the all subsequent write will block. let sized_8_data: [u8; 8] = (u64::MAX - 1).to_ne_bytes(); let res: i64 = unsafe { diff --git a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs index eecf6abb9379f..6a6d363eea6bb 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs @@ -16,8 +16,7 @@ use libc_utils::*; fn main() { // Create an epoll instance. - let epfd = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd, -1); + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Create two socketpair instances. let mut fds_a = [-1, -1]; diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs index 3eb79121a2f8d..22fe014d5831c 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs @@ -7,6 +7,7 @@ use std::thread; #[path = "../../utils/libc.rs"] mod libc_utils; use libc_utils::epoll::*; +use libc_utils::*; // Test if only one thread is unblocked if multiple threads blocked on same epfd. // Expected execution: @@ -16,14 +17,13 @@ use libc_utils::epoll::*; // 4. Thread 1 deadlocks. fn main() { // Create an epoll instance. - let epfd = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd, -1); + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Create an eventfd instance. let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; - let fd1 = unsafe { libc::eventfd(0, flags) }; + let fd1 = errno_result(unsafe { libc::eventfd(0, flags) }).unwrap(); // Make a duplicate so that we have two file descriptors for the same file description. - let fd2 = unsafe { libc::dup(fd1) }; + let fd2 = errno_result(unsafe { libc::dup(fd1) }).unwrap(); // Register both with epoll. epoll_ctl_add(epfd, fd1, EPOLLIN | EPOLLOUT | EPOLLET).unwrap(); diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_unsupported_fd.rs b/src/tools/miri/tests/fail-dep/libc/libc_epoll_unsupported_fd.rs index 59cf0fc2ba026..d611feb30a703 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_unsupported_fd.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_unsupported_fd.rs @@ -1,13 +1,15 @@ //@only-target: linux android illumos +#[path = "../../utils/libc.rs"] +mod libc_utils; +use libc_utils::*; + // This is a test for registering unsupported fd with epoll. // Register epoll fd with epoll is allowed in real system, but we do not support this. fn main() { // Create two epoll instance. - let epfd0 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd0, -1); - let epfd1 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd1, -1); + let epfd0 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); + let epfd1 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Register epoll with epoll. let mut ev = diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs index 75eb06bc12cfb..90f70064932c1 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs @@ -146,7 +146,7 @@ fn test_epoll_ctl_del() { events: (EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO) as u32, u64: u64::try_from(fds[1]).unwrap(), }; - let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + let res = unsafe { libc::epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_eq!(res, 0); // Test EPOLL_CTL_DEL. @@ -158,10 +158,8 @@ fn test_epoll_ctl_del() { // This test is for one fd registered under two different epoll instance. fn test_two_epoll_instance() { // Create two epoll instance. - let epfd1 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd1, -1); - let epfd2 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd2, -1); + let epfd1 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); + let epfd2 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Create a socketpair instance. let mut fds = [-1, -1]; @@ -570,8 +568,7 @@ fn test_epoll_ctl_epfd_equal_fd() { // epfd that shouldn't receive a notification in edge-triggered mode. fn test_epoll_ctl_notification() { // Create an epoll instance. - let epfd0 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd0, -1); + let epfd0 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Create a socketpair instance. let mut fds = [-1, -1]; @@ -584,8 +581,7 @@ fn test_epoll_ctl_notification() { check_epoll_wait_noblock(epfd0, &[Ev { events: EPOLLOUT, data: fds[0] }]); // Create another epoll instance. - let epfd1 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd1, -1); + let epfd1 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Register the same file description for epfd1. epoll_ctl_add(epfd1, fds[0], EPOLLIN | EPOLLOUT | EPOLLET_OR_ZERO).unwrap(); @@ -692,8 +688,7 @@ fn test_issue_3858() { /// Ensure that if a socket becomes un-writable, we don't see it any more. fn test_issue_4374() { // Create an epoll instance. - let epfd0 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd0, -1); + let epfd0 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Create a socketpair instance, make it non-blocking. let mut fds = [-1, -1]; @@ -721,8 +716,7 @@ fn test_issue_4374() { /// Same as above, but for becoming un-readable. fn test_issue_4374_reads() { // Create an epoll instance. - let epfd0 = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd0, -1); + let epfd0 = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Create a socketpair instance, make it non-blocking. let mut fds = [-1, -1]; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index e86c70b590b36..fac5d6e7e02ad 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -9,6 +9,7 @@ use std::{io, thread}; #[path = "../../utils/libc.rs"] mod libc_utils; +use libc_utils::*; fn main() { test_read_write(); @@ -35,8 +36,8 @@ fn write_bytes(fd: i32, data: [u8; N]) -> io::Result { } fn test_read_write() { - let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + let fd = + errno_result(unsafe { libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC) }).unwrap(); let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); // Write 1 to the counter. let res = write_bytes(fd, sized_8_data).unwrap(); @@ -97,8 +98,9 @@ fn test_read_write() { fn test_race() { static mut VAL: u8 = 0; - let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + + let fd = + errno_result(unsafe { libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC) }).unwrap(); let thread1 = thread::spawn(move || { let mut buf: [u8; 8] = [0; 8]; let res = read_bytes(fd, &mut buf).unwrap(); @@ -130,8 +132,7 @@ fn test_syscall() { // This test will block on eventfd read then get unblocked by `write`. fn test_blocking_read() { // eventfd read will block when EFD_NONBLOCK flag is clear and counter = 0. - let flags = libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + let fd = errno_result(unsafe { libc::eventfd(0, libc::EFD_CLOEXEC) }).unwrap(); let thread1 = thread::spawn(move || { let mut buf: [u8; 8] = [0; 8]; // This will block. @@ -154,8 +155,7 @@ fn test_blocking_read() { fn test_blocking_write() { // eventfd write will block when EFD_NONBLOCK flag is clear // and the addition caused counter to exceed u64::MAX - 1. - let flags = libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + let fd = errno_result(unsafe { libc::eventfd(0, libc::EFD_CLOEXEC) }).unwrap(); // Write u64 - 1, so the all subsequent write will block. let sized_8_data: [u8; 8] = (u64::MAX - 1).to_ne_bytes(); let res: i64 = unsafe { @@ -192,8 +192,7 @@ fn test_blocking_write() { fn test_two_threads_blocked_on_eventfd() { // eventfd write will block when EFD_NONBLOCK flag is clear // and the addition caused counter to exceed u64::MAX - 1. - let flags = libc::EFD_CLOEXEC; - let fd = unsafe { libc::eventfd(0, flags) }; + let fd = errno_result(unsafe { libc::eventfd(0, libc::EFD_CLOEXEC) }).unwrap(); // Write u64 - 1, so the all subsequent write will block. let sized_8_data: [u8; 8] = (u64::MAX - 1).to_ne_bytes(); let res: i64 = unsafe { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index a131112ee258d..71f077b0a4397 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -272,7 +272,7 @@ fn test_dup() { let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); unsafe { - let fd = libc::open(name.as_ptr(), libc::O_RDONLY); + let fd = errno_result(libc::open(name.as_ptr(), libc::O_RDONLY)).unwrap(); let new_fd = libc::dup(fd); let new_fd2 = libc::dup2(fd, 8); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs index 9ed0b9c735979..3d39723d43752 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs @@ -359,7 +359,7 @@ fn test_shutdown_read_write() { let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); let client_sockfd = unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; - let epfd = unsafe { libc::epoll_create1(0) }; + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Spawn the server thread. let server_thread = thread::spawn(move || net::accept_ipv4(server_sockfd).unwrap()); @@ -387,7 +387,7 @@ fn test_shutdown_read() { let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); let client_sockfd = unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; - let epfd = unsafe { libc::epoll_create1(0) }; + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Spawn the server thread. let server_thread = thread::spawn(move || net::accept_ipv4(server_sockfd).unwrap()); @@ -411,7 +411,7 @@ fn test_shutdown_write() { let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); let client_sockfd = unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; - let epfd = unsafe { libc::epoll_create1(0) }; + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); // Spawn the server thread. let server_thread = thread::spawn(move || { From d2c6980911d7f19aae70b6fe1457c639c011c017 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jun 2026 14:18:27 +0200 Subject: [PATCH 49/77] =?UTF-8?q?rename=20read=5Fsplit=5Fslice=20=E2=86=92?= =?UTF-8?q?=20read=5Fpartial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tools/miri/tests/pass-dep/libc/libc-pipe.rs | 2 +- src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs | 8 ++++---- src/tools/miri/tests/utils/libc.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs index 98d7340fa9db3..256997babd25f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs @@ -39,7 +39,7 @@ fn test_pipe() { let data = b"123"; write_all(fds[1], data).unwrap(); let mut buf4: [u8; 5] = [0; 5]; - let (part1, rest) = read_split_slice(fds[0], &mut buf4).unwrap(); + let (part1, rest) = read_partial(fds[0], &mut buf4).unwrap(); assert_eq!(part1[..], data[..part1.len()]); // Write 2 more bytes so we can exactly fill the `rest`. write_all(fds[1], b"34").unwrap(); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs index da521600d84a6..2508f0c7030ac 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs @@ -34,7 +34,7 @@ fn test_socketpair() { let data = b"abc"; write_all(fds[0], data).unwrap(); let mut buf2: [u8; 5] = [0; 5]; - let (read, rest) = read_split_slice(fds[1], &mut buf2).unwrap(); + let (read, rest) = read_partial(fds[1], &mut buf2).unwrap(); assert_eq!(read[..], data[..read.len()]); // Write 2 more bytes so we can exactly fill the `rest`. write_all(fds[0], b"12").unwrap(); @@ -52,7 +52,7 @@ fn test_socketpair() { let data = b"abc"; write_all(fds[1], data).unwrap(); let mut buf4: [u8; 5] = [0; 5]; - let (read, rest) = read_split_slice(fds[0], &mut buf4).unwrap(); + let (read, rest) = read_partial(fds[0], &mut buf4).unwrap(); assert_eq!(read[..], data[..read.len()]); // Write 2 more bytes so we can exactly fill the `rest`. write_all(fds[1], b"12").unwrap(); @@ -64,9 +64,9 @@ fn test_socketpair() { errno_check(unsafe { libc::close(fds[0]) }); // Reading the other end should return that data, then EOF. let mut buf: [u8; 5] = [0; 5]; - let (read, _tail) = read_split_slice(fds[1], &mut buf).unwrap(); + let (read, _tail) = read_partial(fds[1], &mut buf).unwrap(); assert_eq!(read, data); - let (read, _tail) = read_split_slice(fds[1], &mut buf).unwrap(); + let (read, _tail) = read_partial(fds[1], &mut buf).unwrap(); assert_eq!(read, &[]); // Writing the other end should emit EPIPE. let err = write_all(fds[1], &mut buf).unwrap_err(); diff --git a/src/tools/miri/tests/utils/libc.rs b/src/tools/miri/tests/utils/libc.rs index f46e6aad01a5b..0f762ed916de5 100644 --- a/src/tools/miri/tests/utils/libc.rs +++ b/src/tools/miri/tests/utils/libc.rs @@ -86,7 +86,7 @@ pub fn read_exact_array(fd: libc::c_int) -> io::Result<[u8; N]> /// Do a single read from `fd` and return the part of the buffer that was written into, /// and the rest. #[track_caller] -pub fn read_split_slice(fd: libc::c_int, buf: &mut [u8]) -> io::Result<(&mut [u8], &mut [u8])> { +pub fn read_partial(fd: libc::c_int, buf: &mut [u8]) -> io::Result<(&mut [u8], &mut [u8])> { let res = errno_result(unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len()) })?; Ok(buf.split_at_mut(res as usize)) } From 5445de0403afe154fecacd577d1e7e188e57a1a5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jun 2026 14:35:07 +0200 Subject: [PATCH 50/77] remove dangling comment --- .../miri/tests/fail-dep/libc/socketpair_block_read_twice.rs | 1 - .../miri/tests/fail-dep/libc/socketpair_block_write_twice.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.rs b/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.rs index 37aa4590647b4..edf3f405056f4 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/socketpair_block_read_twice.rs @@ -1,5 +1,4 @@ //@ignore-target: windows # No libc socketpair on Windows -// test_race depends on a deterministic schedule. //@compile-flags: -Zmiri-deterministic-concurrency //@error-in-other-file: deadlock //@require-annotations-for-level: error diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.rs b/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.rs index 2f8b5be0c0c57..d062aeaf34873 100644 --- a/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/socketpair_block_write_twice.rs @@ -1,5 +1,4 @@ //@ignore-target: windows # No libc socketpair on Windows -// test_race depends on a deterministic schedule. //@compile-flags: -Zmiri-deterministic-concurrency //@error-in-other-file: deadlock //@require-annotations-for-level: error From ab8866908ba2cb1ba4f32b31dfa5a4ec0a040d49 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Thu, 25 Jun 2026 13:04:25 +0000 Subject: [PATCH 51/77] replace cfg_if with cfg_select --- src/tools/miri/tests/deps/Cargo.toml | 1 - src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 7 +- .../tests/pass-dep/libc/pthread-threadname.rs | 84 +++++++++++-------- src/tools/miri/tests/pass-dep/shims/gettid.rs | 28 ++++--- 4 files changed, 71 insertions(+), 49 deletions(-) diff --git a/src/tools/miri/tests/deps/Cargo.toml b/src/tools/miri/tests/deps/Cargo.toml index a4d06b628081c..bbbcc316f31c2 100644 --- a/src/tools/miri/tests/deps/Cargo.toml +++ b/src/tools/miri/tests/deps/Cargo.toml @@ -10,7 +10,6 @@ edition = "2021" # all dependencies (and their transitive ones) listed here can be used in `tests/*-dep`. libc = "0.2" num_cpus = "1.10.1" -cfg-if = "1" getrandom_01 = { package = "getrandom", version = "0.1" } getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index a131112ee258d..5f6aacc641238 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -856,8 +856,8 @@ fn test_readdir() { assert!(!dirp.is_null()); let mut entries = Vec::new(); loop { - cfg_if::cfg_if! { - if #[cfg(target_os = "macos")] { + cfg_select! { + target_os = "macos" => { // On macos we only support readdir_r as that's what std uses there. use std::mem::MaybeUninit; use libc::dirent; @@ -866,7 +866,8 @@ fn test_readdir() { let ret = libc::readdir_r(dirp, entry.as_mut_ptr(), &mut result); assert_eq!(ret, 0); let entry_ptr = result; - } else { + } + _ => { let entry_ptr = libc::readdir(dirp); } } diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs index cf7ea4c6abba1..6cba672c6569c 100644 --- a/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs +++ b/src/tools/miri/tests/pass-dep/libc/pthread-threadname.rs @@ -4,17 +4,21 @@ use std::ffi::{CStr, CString}; use std::thread; const MAX_THREAD_NAME_LEN: usize = { - cfg_if::cfg_if! { - if #[cfg(any(target_os = "linux"))] { + cfg_select! { + target_os = "linux" => { 16 - } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] { + } + any(target_os = "illumos", target_os = "solaris") => { 32 - } else if #[cfg(target_os = "macos")] { + } + target_os = "macos" => { libc::MAXTHREADNAMESIZE // 64, at the time of writing - } else if #[cfg(target_os = "freebsd")] { + } + target_os = "freebsd" => { usize::MAX // as far as I can tell - } else { - panic!() + } + _ => { + compile_error!("unsupported OS"); } } }; @@ -28,35 +32,38 @@ fn main() { .collect::(); fn set_thread_name(name: &CStr) -> i32 { - cfg_if::cfg_if! { - if #[cfg(any( + cfg_select! { + any( target_os = "linux", target_os = "freebsd", target_os = "illumos", target_os = "solaris" - ))] { + ) => { unsafe { libc::pthread_setname_np(libc::pthread_self(), name.as_ptr().cast()) } - } else if #[cfg(target_os = "macos")] { + } + target_os = "macos" => { unsafe { libc::pthread_setname_np(name.as_ptr().cast()) } - } else { + } + _ => { compile_error!("set_thread_name not supported for this OS") } } } fn get_thread_name(name: &mut [u8]) -> i32 { - cfg_if::cfg_if! { - if #[cfg(any( + cfg_select! { + any( target_os = "linux", target_os = "freebsd", target_os = "illumos", target_os = "solaris", target_os = "macos" - ))] { + ) => { unsafe { libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len()) } - } else { + } + _ => { compile_error!("get_thread_name not supported for this OS") } } @@ -95,13 +102,14 @@ fn main() { // Test what happens when the buffer is shorter than 16, but still long enough. let res = get_thread_name(&mut buf[..15]); - cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { + cfg_select! { + target_os = "linux" => { // For glibc used by linux-gnu there should be a failue, // if a shorter than 16 bytes buffer is provided, even if that would be // large enough for the thread name. assert_eq!(res, libc::ERANGE); - } else { + } + _ => { // Everywhere else, this should work. assert_eq!(res, 0); // POSIX seems to promise at least 15 chars excluding a null terminator. @@ -112,15 +120,16 @@ fn main() { // Test what happens when the buffer is too short even for the short name. let res = get_thread_name(&mut buf[..4]); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "freebsd", target_os = "macos"))] { + cfg_select! { + any(target_os = "freebsd", target_os = "macos") => { // On macOS and FreeBSD it's not an error for the buffer to be // too short for the thread name -- they truncate instead. assert_eq!(res, 0); let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); assert_eq!(cstr.to_bytes_with_nul().len(), 4); assert!(short_name.as_bytes().starts_with(cstr.to_bytes())); - } else { + } + _ => { // The rest should give an error. assert_eq!(res, libc::ERANGE); } @@ -128,12 +137,13 @@ fn main() { // Test zero-sized buffer. let res = get_thread_name(&mut []); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "freebsd", target_os = "macos"))] { + cfg_select! { + any(target_os = "freebsd", target_os = "macos") => { // On macOS and FreeBSD it's not an error for the buffer to be // too short for the thread name -- even with size 0. assert_eq!(res, 0); - } else { + } + _ => { // The rest should give an error. assert_eq!(res, libc::ERANGE); } @@ -149,16 +159,18 @@ fn main() { // Set full thread name. let cstr = CString::new(long_name.clone()).unwrap(); let res = set_thread_name(&cstr); - cfg_if::cfg_if! { - if #[cfg(target_os = "freebsd")] { + cfg_select! { + target_os = "freebsd" => { // Names of all size are supported. assert!(cstr.to_bytes_with_nul().len() <= MAX_THREAD_NAME_LEN); assert_eq!(res, 0); - } else if #[cfg(target_os = "macos")] { + } + target_os = "macos" => { // Name is too long. assert!(cstr.to_bytes_with_nul().len() > MAX_THREAD_NAME_LEN); assert_eq!(res, libc::ENAMETOOLONG); - } else { + } + _ => { // Name is too long. assert!(cstr.to_bytes_with_nul().len() > MAX_THREAD_NAME_LEN); assert_eq!(res, libc::ERANGE); @@ -179,14 +191,15 @@ fn main() { // Test what happens when our buffer is just one byte too small. let res = get_thread_name(&mut buf[..truncated_name.len()]); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "freebsd", target_os = "macos"))] { + cfg_select! { + any(target_os = "freebsd", target_os = "macos") => { // On macOS and FreeBSD it's not an error for the buffer to be // too short for the thread name -- they truncate instead. assert_eq!(res, 0); let cstr = CStr::from_bytes_until_nul(&buf).unwrap(); assert_eq!(cstr.to_bytes(), &truncated_name.as_bytes()[..(truncated_name.len() - 1)]); - } else { + } + _ => { // The rest should give an error. assert_eq!(res, libc::ERANGE); } @@ -199,10 +212,11 @@ fn main() { // Now set the name for a non-existing thread and verify error codes. let invalid_thread = 0xdeadbeef; let error = { - cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { + cfg_select! { + target_os = "linux" => { libc::ENOENT - } else { + } + _ => { libc::ESRCH } } diff --git a/src/tools/miri/tests/pass-dep/shims/gettid.rs b/src/tools/miri/tests/pass-dep/shims/gettid.rs index 0dce7bdc0c52e..9b186699ce275 100644 --- a/src/tools/miri/tests/pass-dep/shims/gettid.rs +++ b/src/tools/miri/tests/pass-dep/shims/gettid.rs @@ -5,29 +5,37 @@ #![feature(linkage)] fn gettid() -> u64 { - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { + cfg_select! { + any(target_os = "android", target_os = "linux") => { gettid_linux_like() - } else if #[cfg(target_os = "nto")] { + } + target_os = "nto" => { unsafe { libc::gettid() as u64 } - } else if #[cfg(target_os = "openbsd")] { + } + target_os = "openbsd" => { unsafe { libc::getthrid() as u64 } - } else if #[cfg(target_os = "freebsd")] { + } + target_os = "freebsd" => { unsafe { libc::pthread_getthreadid_np() as u64 } - } else if #[cfg(target_os = "netbsd")] { + } + target_os = "netbsd" => { unsafe { libc::_lwp_self() as u64 } - } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { + } + any(target_os = "solaris", target_os = "illumos") => { // On Solaris and Illumos, the `pthread_t` is the OS TID. unsafe { libc::pthread_self() as u64 } - } else if #[cfg(target_vendor = "apple")] { + } + target_vendor = "apple" => { let mut id = 0u64; let status: libc::c_int = unsafe { libc::pthread_threadid_np(0, &mut id) }; assert_eq!(status, 0); id - } else if #[cfg(windows)] { + } + windows => { use windows_sys::Win32::System::Threading::GetCurrentThreadId; unsafe { GetCurrentThreadId() as u64 } - } else { + } + _ => { compile_error!("platform has no gettid") } } From 37ffa9ad058f4b29203da82f79b9de2870b637b0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jun 2026 14:52:05 +0200 Subject: [PATCH 52/77] run some more tests natively --- .../miri/tests/pass-dep/libc/libc-eventfd.rs | 6 + .../miri/tests/pass-dep/libc/libc-pipe.rs | 1 + .../tests/pass-dep/libc/libc-socketpair.rs | 6 + .../miri/tests/pass-dep/libc/libc-time.rs | 104 +++++++++++------- 4 files changed, 80 insertions(+), 37 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index e86c70b590b36..d32d5ecf05e4f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -1,6 +1,7 @@ //@only-target: linux android illumos // test_race, test_blocking_read and test_blocking_write depend on a deterministic schedule. //@compile-flags: -Zmiri-deterministic-concurrency +//@run-native // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] @@ -100,6 +101,11 @@ fn test_race() { let flags = libc::EFD_NONBLOCK | libc::EFD_CLOEXEC; let fd = unsafe { libc::eventfd(0, flags) }; let thread1 = thread::spawn(move || { + if !cfg!(miri) { + // Make sure the write goes first. + thread::sleep(std::time::Duration::from_millis(10)); + } + let mut buf: [u8; 8] = [0; 8]; let res = read_bytes(fd, &mut buf).unwrap(); // read returns number of bytes has been read, which is always 8. diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs index 98d7340fa9db3..91b89aaf97d6b 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs @@ -1,6 +1,7 @@ //@ignore-target: windows # No libc pipe on Windows // test_race depends on a deterministic schedule. //@compile-flags: -Zmiri-deterministic-concurrency +//@run-native use std::thread; #[path = "../../utils/libc.rs"] diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs index da521600d84a6..af351802eec83 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs @@ -1,6 +1,7 @@ //@ignore-target: windows # No libc socketpair on Windows // test_race depends on a deterministic schedule. //@compile-flags: -Zmiri-deterministic-concurrency +//@run-native // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] @@ -132,6 +133,11 @@ fn test_blocking_read() { // Test the behaviour of a socketpair getting blocked on write and subsequently unblocked. fn test_blocking_write() { + // The test uses Miri's exact buffer size. + if !cfg!(miri) { + return; + } + let mut fds = [-1, -1]; errno_check(unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }); let arr1: [u8; 0x34000] = [1; 0x34000]; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-time.rs b/src/tools/miri/tests/pass-dep/libc/libc-time.rs index f315d2ab117f9..3bfcfab099d7b 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-time.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-time.rs @@ -1,5 +1,6 @@ //@ignore-target: windows # no libc time APIs on Windows //@compile-flags: -Zmiri-disable-isolation +//@run-native #[path = "../../utils/libc.rs"] mod libc_utils; @@ -9,6 +10,17 @@ use std::{env, mem, ptr}; use libc_utils::errno_check; +fn set_tz(name: &str) { + extern "C" { + fn tzset(); + } + + env::set_var("TZ", name); + if !cfg!(miri) { + unsafe { tzset() }; // re-read TZ env var (natively, it may be cached) + } +} + fn main() { test_clocks(); test_posix_gettimeofday(); @@ -66,11 +78,13 @@ fn test_posix_gettimeofday() { assert!(tv.tv_sec > 0); assert!(tv.tv_usec >= 0); // Theoretically this could be 0. - // Test that non-null tz returns an error (because we don't support it). - let mut tz = mem::MaybeUninit::::uninit(); - let tz_ptr = tz.as_mut_ptr(); - let is_error = unsafe { libc::gettimeofday(tp.as_mut_ptr(), tz_ptr.cast()) }; - assert_eq!(is_error, -1); + if cfg!(miri) { + // Test that non-null tz returns an error (because we don't support it). + let mut tz = mem::MaybeUninit::::uninit(); + let tz_ptr = tz.as_mut_ptr(); + let is_error = unsafe { libc::gettimeofday(tp.as_mut_ptr(), tz_ptr.cast()) }; + assert_eq!(is_error, -1); + } } /// Helper function to create an empty tm struct. @@ -104,9 +118,8 @@ fn create_empty_tm() -> libc::tm { /// Original GMT test fn test_localtime_r_gmt() { - // Set timezone to GMT. - let key = "TZ"; - env::set_var(key, "GMT"); + set_tz("GMT"); + const TIME_SINCE_EPOCH: libc::time_t = 1712475836; // 2024-04-07 07:43:56 GMT let custom_time_ptr = &TIME_SINCE_EPOCH; let mut tm = create_empty_tm(); @@ -120,7 +133,9 @@ fn test_localtime_r_gmt() { assert_eq!(tm.tm_year, 124); assert_eq!(tm.tm_wday, 0); assert_eq!(tm.tm_yday, 97); - assert_eq!(tm.tm_isdst, -1); + if cfg!(miri) { + assert_eq!(tm.tm_isdst, -1); + } #[cfg(any( target_os = "linux", target_os = "macos", @@ -130,21 +145,21 @@ fn test_localtime_r_gmt() { { assert_eq!(tm.tm_gmtoff, 0); unsafe { - assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00"); + assert_eq!( + std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), + if cfg!(miri) { "+00" } else { "GMT" } + ); } } // The returned value is the pointer passed in. assert!(ptr::eq(res, &mut tm)); - - // Remove timezone setting. - env::remove_var(key); } /// PST timezone test (testing different timezone handling). fn test_localtime_r_pst() { - let key = "TZ"; - env::set_var(key, "PST8PDT"); + set_tz("PST8PDT"); + const TIME_SINCE_EPOCH: libc::time_t = 1712475836; // 2024-04-07 07:43:56 GMT let custom_time_ptr = &TIME_SINCE_EPOCH; let mut tm = create_empty_tm(); @@ -159,7 +174,9 @@ fn test_localtime_r_pst() { assert_eq!(tm.tm_year, 124); assert_eq!(tm.tm_wday, 0); assert_eq!(tm.tm_yday, 97); - assert_eq!(tm.tm_isdst, -1); // DST information unavailable + if cfg!(miri) { + assert_eq!(tm.tm_isdst, -1); // DST information unavailable + } #[cfg(any( target_os = "linux", @@ -170,18 +187,20 @@ fn test_localtime_r_pst() { { assert_eq!(tm.tm_gmtoff, -7 * 3600); // -7 hours in seconds unsafe { - assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "-07"); + assert_eq!( + std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), + if cfg!(miri) { "-07" } else { "PDT" } + ); } } assert!(ptr::eq(res, &mut tm)); - env::remove_var(key); } /// Unix epoch test (edge case testing). fn test_localtime_r_epoch() { - let key = "TZ"; - env::set_var(key, "GMT"); + set_tz("GMT"); + const TIME_SINCE_EPOCH: libc::time_t = 0; // 1970-01-01 00:00:00 let custom_time_ptr = &TIME_SINCE_EPOCH; let mut tm = create_empty_tm(); @@ -196,7 +215,9 @@ fn test_localtime_r_epoch() { assert_eq!(tm.tm_year, 70); assert_eq!(tm.tm_wday, 4); // Thursday assert_eq!(tm.tm_yday, 0); - assert_eq!(tm.tm_isdst, -1); + if cfg!(miri) { + assert_eq!(tm.tm_isdst, -1); + } #[cfg(any( target_os = "linux", @@ -207,19 +228,20 @@ fn test_localtime_r_epoch() { { assert_eq!(tm.tm_gmtoff, 0); unsafe { - assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00"); + assert_eq!( + std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), + if cfg!(miri) { "+00" } else { "GMT" } + ); } } assert!(ptr::eq(res, &mut tm)); - env::remove_var(key); } /// Future date test (testing large values). #[cfg(target_pointer_width = "64")] fn test_localtime_r_future_64b() { - let key = "TZ"; - env::set_var(key, "GMT"); + set_tz("GMT"); // Using 2050-01-01 00:00:00 for 64-bit systems // value that's safe for 64-bit time_t @@ -237,7 +259,9 @@ fn test_localtime_r_future_64b() { assert_eq!(tm.tm_year, 150); // 2050 - 1900 assert_eq!(tm.tm_wday, 6); // Saturday assert_eq!(tm.tm_yday, 0); - assert_eq!(tm.tm_isdst, -1); + if cfg!(miri) { + assert_eq!(tm.tm_isdst, -1); + } #[cfg(any( target_os = "linux", @@ -248,19 +272,20 @@ fn test_localtime_r_future_64b() { { assert_eq!(tm.tm_gmtoff, 0); unsafe { - assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00"); + assert_eq!( + std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), + if cfg!(miri) { "+00" } else { "GMT" } + ); } } assert!(ptr::eq(res, &mut tm)); - env::remove_var(key); } /// Future date test (testing large values for 32b target). #[cfg(target_pointer_width = "32")] fn test_localtime_r_future_32b() { - let key = "TZ"; - env::set_var(key, "GMT"); + set_tz("GMT"); // Using 2030-01-01 00:00:00 for 32-bit systems // Safe value within i32 range @@ -279,7 +304,9 @@ fn test_localtime_r_future_32b() { assert_eq!(tm.tm_year, 130); // 2030 - 1900 assert_eq!(tm.tm_wday, 2); // Tuesday assert_eq!(tm.tm_yday, 0); - assert_eq!(tm.tm_isdst, -1); + if cfg!(miri) { + assert_eq!(tm.tm_isdst, -1); + } #[cfg(any( target_os = "linux", @@ -290,19 +317,20 @@ fn test_localtime_r_future_32b() { { assert_eq!(tm.tm_gmtoff, 0); unsafe { - assert_eq!(std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), "+00"); + assert_eq!( + std::ffi::CStr::from_ptr(tm.tm_zone).to_str().unwrap(), + if cfg!(miri) { "+00" } else { "GMT" } + ); } } assert!(ptr::eq(res, &mut tm)); - env::remove_var(key); } /// Tests the behavior of `localtime_r` with multiple calls to ensure deduplication of `tm_zone` pointers. #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd", target_os = "android"))] fn test_localtime_r_multiple_calls_deduplication() { - let key = "TZ"; - env::set_var(key, "PST8PDT"); + set_tz("PST8PDT"); const TIME_SINCE_EPOCH_BASE: libc::time_t = 1712475836; // Base timestamp: 2024-04-07 07:43:56 GMT const NUM_CALLS: usize = 50; @@ -321,9 +349,11 @@ fn test_localtime_r_multiple_calls_deduplication() { let unique_count = unique_pointers.len(); + // Miri non-determinisitcally de-duplicates. Native always deduplicates. + let min = if cfg!(miri) { 2 } else { 1 }; assert!( - unique_count >= 2 && unique_count <= (NUM_CALLS - 1), - "Unexpected number of unique tm_zone pointers: {} (expected between 2 and {})", + unique_count >= min && unique_count <= (NUM_CALLS - 1), + "Unexpected number of unique tm_zone pointers: {} (expected between {min} and {})", unique_count, NUM_CALLS - 1 ); From 528bd23ff58bd43787708ea7a5e1a06c7e369291 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jun 2026 16:35:51 +0200 Subject: [PATCH 53/77] update lockfile --- src/tools/miri/tests/deps/Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/miri/tests/deps/Cargo.lock b/src/tools/miri/tests/deps/Cargo.lock index cbd2aa22b5236..4691588eefb40 100644 --- a/src/tools/miri/tests/deps/Cargo.lock +++ b/src/tools/miri/tests/deps/Cargo.lock @@ -290,7 +290,6 @@ dependencies = [ name = "miri-test-deps" version = "0.1.0" dependencies = [ - "cfg-if", "futures", "getrandom 0.1.16", "getrandom 0.2.17", From 4a2d36a1f9de30e0a97f6b0f70e284b200c7b090 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 26 Jun 2026 05:45:57 +0000 Subject: [PATCH 54/77] Prepare for merging from rust-lang/rust This updates the rust-version file to 40557f6225e337d68c8d4f086557ce54135f5dd9. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 5db47ca8fc59b..10d09bd1f1ebd 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -942ac9ce4116d4ea784c9882659372b34978b1f8 +40557f6225e337d68c8d4f086557ce54135f5dd9 From 58f80da065eede67f1476ecd5f30006e62dcc2fe Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Fri, 26 Jun 2026 15:35:41 +0800 Subject: [PATCH 55/77] Fix inconsistent safety requirement in VecDeque::nonoverlapping_ranges --- library/alloc/src/collections/vec_deque/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 5a900db9d1ce8..065cc128101ae 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -267,7 +267,7 @@ impl VecDeque { /// /// - Ranges must not overlap: `src.abs_diff(dst) >= count`. /// - Ranges must be in bounds of the logical buffer: `src + count <= self.capacity()` and `dst + count <= self.capacity()`. - /// - `head` must be in bounds: `head < self.capacity()`. + /// - `head` must be in bounds: `head < self.capacity()`, unless `self.capacity() == 0`, in which case `head == 0`. #[cfg(not(no_global_oom_handling))] unsafe fn nonoverlapping_ranges( &mut self, From 3c00af96ba6cd3de91a96066d8b5037f11747482 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 5 Feb 2026 12:55:37 +0100 Subject: [PATCH 56/77] Add supertrait item shadowing for type-level path resolution --- .../src/hir_ty_lowering/errors.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 76 ++++++++++++++++++- .../supertrait-shadowing/assoc-const2.rs | 32 ++++++++ .../assoc-const2.run.stdout | 2 + .../supertrait-shadowing/assoc-type.rs | 47 ++++++++++++ .../assoc-type.run.stdout | 4 + 6 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 tests/ui/methods/supertrait-shadowing/assoc-const2.rs create mode 100644 tests/ui/methods/supertrait-shadowing/assoc-const2.run.stdout create mode 100644 tests/ui/methods/supertrait-shadowing/assoc-type.rs create mode 100644 tests/ui/methods/supertrait-shadowing/assoc-type.run.stdout diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 39402cfc35dce..32678e8a5a12f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -409,9 +409,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub(super) fn report_ambiguous_assoc_item( &self, - bound1: ty::PolyTraitRef<'tcx>, - bound2: ty::PolyTraitRef<'tcx>, - matching_candidates: impl Iterator>, + matching_candidates: &[ty::PolyTraitRef<'tcx>], qself: AssocItemQSelf, assoc_tag: ty::AssocTag, assoc_ident: Ident, @@ -443,7 +441,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // predicates!). // FIXME: Turn this into a structured, translatable & more actionable suggestion. let mut where_bounds = vec![]; - for bound in [bound1, bound2].into_iter().chain(matching_candidates) { + for &bound in matching_candidates { let bound_id = bound.def_id(); let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind( tcx, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index baa9fddc2a651..5785de6c07845 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -24,6 +24,7 @@ use std::{assert_matches, slice}; use rustc_abi::FIRST_VARIANT; use rustc_ast::LitKind; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::sso::SsoHashSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey, @@ -1262,6 +1263,69 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } + /// When there are multiple traits which contain an identically named + /// associated item, this function eliminates any traits which are a + /// supertrait of another candidate trait. + /// + /// This implements RFC #3624. + fn collapse_candidates_to_subtrait_pick( + &self, + matching_candidates: &[ty::PolyTraitRef<'tcx>], + ) -> Option> { + if !self.tcx().features().supertrait_item_shadowing() { + return None; + } + + let mut child_trait = matching_candidates[0]; + let mut supertraits: SsoHashSet<_> = + traits::supertrait_def_ids(self.tcx(), child_trait.def_id()).collect(); + + let mut remaining_candidates: Vec<_> = matching_candidates[1..].iter().copied().collect(); + while !remaining_candidates.is_empty() { + let mut made_progress = false; + let mut next_round = vec![]; + + for remaining_trait in remaining_candidates { + if supertraits.contains(&remaining_trait.def_id()) { + made_progress = true; + continue; + } + + // This pick is not a supertrait of the `child_pick`. + // Check if it's a subtrait of the `child_pick`, instead. + // If it is, then it must have been a subtrait of every + // other pick we've eliminated at this point. It will + // take over at this point. + let remaining_trait_supertraits: SsoHashSet<_> = + traits::supertrait_def_ids(self.tcx(), remaining_trait.def_id()).collect(); + if remaining_trait_supertraits.contains(&child_trait.def_id()) { + child_trait = remaining_trait; + supertraits = remaining_trait_supertraits; + made_progress = true; + continue; + } + + // `child_pick` is not a supertrait of this pick. + // Don't bail here, since we may be comparing two supertraits + // of a common subtrait. These two supertraits won't be related + // at all, but we will pick them up next round when we find their + // child as we continue iterating in this round. + next_round.push(remaining_trait); + } + + if made_progress { + // If we've made progress, iterate again. + remaining_candidates = next_round; + } else { + // Otherwise, we must have at least two candidates which + // are not related to each other at all.; + return None; + } + } + + Some(child_trait) + } + /// Search for a single trait bound whose trait defines the associated item given by /// `assoc_ident`. /// @@ -1296,10 +1360,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; if let Some(bound2) = matching_candidates.next() { + let all_matching_candidates: Vec<_> = + [bound1, bound2].into_iter().chain(matching_candidates).collect(); + if let Some(bound) = + self.collapse_candidates_to_subtrait_pick(&all_matching_candidates) + { + return Ok(bound); + } + return Err(self.report_ambiguous_assoc_item( - bound1, - bound2, - matching_candidates, + &all_matching_candidates, qself, assoc_tag, assoc_ident, diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const2.rs b/tests/ui/methods/supertrait-shadowing/assoc-const2.rs new file mode 100644 index 0000000000000..ebd0875eac8ea --- /dev/null +++ b/tests/ui/methods/supertrait-shadowing/assoc-const2.rs @@ -0,0 +1,32 @@ +//@ run-pass +//@ check-run-results + +#![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] +#![allow(dead_code)] + +trait A { + const CONST: i32; +} +impl A for T { + const CONST: i32 = 1; +} + +trait B: A { + type const CONST: i32; +} +impl B for T { + type const CONST: i32 = 2; +} + +trait C: B {} +impl C for T {} + +fn main() { + println!("{}", i32::CONST); + generic::(); +} + +fn generic>() { + println!("{}", T::CONST); +} diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const2.run.stdout b/tests/ui/methods/supertrait-shadowing/assoc-const2.run.stdout new file mode 100644 index 0000000000000..51993f072d583 --- /dev/null +++ b/tests/ui/methods/supertrait-shadowing/assoc-const2.run.stdout @@ -0,0 +1,2 @@ +2 +2 diff --git a/tests/ui/methods/supertrait-shadowing/assoc-type.rs b/tests/ui/methods/supertrait-shadowing/assoc-type.rs new file mode 100644 index 0000000000000..7434fa7523119 --- /dev/null +++ b/tests/ui/methods/supertrait-shadowing/assoc-type.rs @@ -0,0 +1,47 @@ +//@ run-pass +//@ check-run-results + +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + type T; +} +impl A for T { + type T = i8; +} + +trait B: A { + type T; +} +impl B for T { + type T = i16; +} + +trait C: B {} +impl C for T {} + +fn main() { + generic::(); + generic2::(); + generic3::(); + generic4::(); +} + +fn generic() { + println!("{}", size_of::()); +} + +fn generic2>() { + println!("{}", size_of::()); +} + +fn generic3>() { + println!("{}", size_of::()); +} + +fn generic4>() { + println!("{}", size_of::()); +} diff --git a/tests/ui/methods/supertrait-shadowing/assoc-type.run.stdout b/tests/ui/methods/supertrait-shadowing/assoc-type.run.stdout new file mode 100644 index 0000000000000..6f9071418f37e --- /dev/null +++ b/tests/ui/methods/supertrait-shadowing/assoc-type.run.stdout @@ -0,0 +1,4 @@ +2 +1 +2 +2 From 1efd5a62d141b4ea013f6bfd875677f7b8dc3b88 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 3 Jun 2026 17:29:02 +0100 Subject: [PATCH 57/77] Address review feedback --- .../src/hir_ty_lowering/mod.rs | 16 ++++++++++------ compiler/rustc_hir_typeck/src/method/probe.rs | 4 ++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5785de6c07845..2d0dab03f2c46 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1267,6 +1267,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// associated item, this function eliminates any traits which are a /// supertrait of another candidate trait. /// + /// This is the type-level analogue of + /// `rustc_hir_typeck::method::probe::ProbeContext::collapse_candidates_to_subtrait_pick`; + /// keep both implementations in sync. + /// /// This implements RFC #3624. fn collapse_candidates_to_subtrait_pick( &self, @@ -1291,8 +1295,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { continue; } - // This pick is not a supertrait of the `child_pick`. - // Check if it's a subtrait of the `child_pick`, instead. + // This candidate is not a supertrait of the `child_trait`. + // Check if it's a subtrait of the `child_trait`, instead. // If it is, then it must have been a subtrait of every // other pick we've eliminated at this point. It will // take over at this point. @@ -1305,7 +1309,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { continue; } - // `child_pick` is not a supertrait of this pick. + // Neither `child_trait` or the current candidate are + // supertraits of each other. // Don't bail here, since we may be comparing two supertraits // of a common subtrait. These two supertraits won't be related // at all, but we will pick them up next round when we find their @@ -1318,7 +1323,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { remaining_candidates = next_round; } else { // Otherwise, we must have at least two candidates which - // are not related to each other at all.; + // are not related to each other at all. return None; } } @@ -1362,8 +1367,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Some(bound2) = matching_candidates.next() { let all_matching_candidates: Vec<_> = [bound1, bound2].into_iter().chain(matching_candidates).collect(); - if let Some(bound) = - self.collapse_candidates_to_subtrait_pick(&all_matching_candidates) + if let Some(bound) = self.collapse_candidates_to_subtrait_pick(&all_matching_candidates) { return Ok(bound); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e8921841c4405..ce187aa1aff14 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2359,6 +2359,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// multiple conflicting picks if there is one pick whose trait container is a subtrait /// of the trait containers of all of the other picks. /// + /// This is the method-probe analogue of + /// `rustc_hir_analysis::hir_ty_lowering::HirTyLowerer::collapse_candidates_to_subtrait_pick`; + /// keep both implementations in sync. + /// /// This implements RFC #3624. fn collapse_candidates_to_subtrait_pick( &self, From e4ef1cff8961155a42c9a47e02d144a925d685a2 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 3 Jun 2026 17:33:44 +0100 Subject: [PATCH 58/77] Move supertrait shadowing tests to tests/ui/supertrait-shadowing --- tests/ui/{methods => }/supertrait-shadowing/assoc-const.rs | 0 tests/ui/{methods => }/supertrait-shadowing/assoc-const2.rs | 0 .../ui/{methods => }/supertrait-shadowing/assoc-const2.run.stdout | 0 tests/ui/{methods => }/supertrait-shadowing/assoc-type.rs | 0 tests/ui/{methods => }/supertrait-shadowing/assoc-type.run.stdout | 0 .../supertrait-shadowing/auxiliary/shadowed_stability.rs | 0 tests/ui/{methods => }/supertrait-shadowing/common-ancestor-2.rs | 0 .../{methods => }/supertrait-shadowing/common-ancestor-2.stderr | 0 tests/ui/{methods => }/supertrait-shadowing/common-ancestor-3.rs | 0 .../{methods => }/supertrait-shadowing/common-ancestor-3.stderr | 0 tests/ui/{methods => }/supertrait-shadowing/common-ancestor.rs | 0 .../ui/{methods => }/supertrait-shadowing/common-ancestor.stderr | 0 tests/ui/{methods => }/supertrait-shadowing/definition-site.rs | 0 .../ui/{methods => }/supertrait-shadowing/definition-site.stderr | 0 .../supertrait-shadowing/false-subtrait-after-inference.rs | 0 .../supertrait-shadowing/false-subtrait-after-inference.stderr | 0 .../ui/{methods => }/supertrait-shadowing/no-common-ancestor-2.rs | 0 .../supertrait-shadowing/no-common-ancestor-2.stderr | 0 tests/ui/{methods => }/supertrait-shadowing/no-common-ancestor.rs | 0 .../{methods => }/supertrait-shadowing/no-common-ancestor.stderr | 0 tests/ui/{methods => }/supertrait-shadowing/out-of-scope.rs | 0 .../supertrait-shadowing/trivially-false-subtrait.rs | 0 tests/ui/{methods => }/supertrait-shadowing/type-dependent.rs | 0 .../{methods => }/supertrait-shadowing/unstable.off_normal.stderr | 0 .../supertrait-shadowing/unstable.off_shadowing.stderr | 0 .../{methods => }/supertrait-shadowing/unstable.on_normal.stderr | 0 tests/ui/{methods => }/supertrait-shadowing/unstable.rs | 0 27 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{methods => }/supertrait-shadowing/assoc-const.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/assoc-const2.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/assoc-const2.run.stdout (100%) rename tests/ui/{methods => }/supertrait-shadowing/assoc-type.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/assoc-type.run.stdout (100%) rename tests/ui/{methods => }/supertrait-shadowing/auxiliary/shadowed_stability.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/common-ancestor-2.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/common-ancestor-2.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/common-ancestor-3.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/common-ancestor-3.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/common-ancestor.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/common-ancestor.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/definition-site.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/definition-site.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/false-subtrait-after-inference.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/false-subtrait-after-inference.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/no-common-ancestor-2.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/no-common-ancestor-2.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/no-common-ancestor.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/no-common-ancestor.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/out-of-scope.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/trivially-false-subtrait.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/type-dependent.rs (100%) rename tests/ui/{methods => }/supertrait-shadowing/unstable.off_normal.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/unstable.off_shadowing.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/unstable.on_normal.stderr (100%) rename tests/ui/{methods => }/supertrait-shadowing/unstable.rs (100%) diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const.rs b/tests/ui/supertrait-shadowing/assoc-const.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/assoc-const.rs rename to tests/ui/supertrait-shadowing/assoc-const.rs diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const2.rs b/tests/ui/supertrait-shadowing/assoc-const2.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/assoc-const2.rs rename to tests/ui/supertrait-shadowing/assoc-const2.rs diff --git a/tests/ui/methods/supertrait-shadowing/assoc-const2.run.stdout b/tests/ui/supertrait-shadowing/assoc-const2.run.stdout similarity index 100% rename from tests/ui/methods/supertrait-shadowing/assoc-const2.run.stdout rename to tests/ui/supertrait-shadowing/assoc-const2.run.stdout diff --git a/tests/ui/methods/supertrait-shadowing/assoc-type.rs b/tests/ui/supertrait-shadowing/assoc-type.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/assoc-type.rs rename to tests/ui/supertrait-shadowing/assoc-type.rs diff --git a/tests/ui/methods/supertrait-shadowing/assoc-type.run.stdout b/tests/ui/supertrait-shadowing/assoc-type.run.stdout similarity index 100% rename from tests/ui/methods/supertrait-shadowing/assoc-type.run.stdout rename to tests/ui/supertrait-shadowing/assoc-type.run.stdout diff --git a/tests/ui/methods/supertrait-shadowing/auxiliary/shadowed_stability.rs b/tests/ui/supertrait-shadowing/auxiliary/shadowed_stability.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/auxiliary/shadowed_stability.rs rename to tests/ui/supertrait-shadowing/auxiliary/shadowed_stability.rs diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/supertrait-shadowing/common-ancestor-2.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/common-ancestor-2.rs rename to tests/ui/supertrait-shadowing/common-ancestor-2.rs diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/common-ancestor-2.stderr rename to tests/ui/supertrait-shadowing/common-ancestor-2.stderr diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/supertrait-shadowing/common-ancestor-3.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/common-ancestor-3.rs rename to tests/ui/supertrait-shadowing/common-ancestor-3.rs diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/common-ancestor-3.stderr rename to tests/ui/supertrait-shadowing/common-ancestor-3.stderr diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.rs b/tests/ui/supertrait-shadowing/common-ancestor.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/common-ancestor.rs rename to tests/ui/supertrait-shadowing/common-ancestor.rs diff --git a/tests/ui/methods/supertrait-shadowing/common-ancestor.stderr b/tests/ui/supertrait-shadowing/common-ancestor.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/common-ancestor.stderr rename to tests/ui/supertrait-shadowing/common-ancestor.stderr diff --git a/tests/ui/methods/supertrait-shadowing/definition-site.rs b/tests/ui/supertrait-shadowing/definition-site.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/definition-site.rs rename to tests/ui/supertrait-shadowing/definition-site.rs diff --git a/tests/ui/methods/supertrait-shadowing/definition-site.stderr b/tests/ui/supertrait-shadowing/definition-site.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/definition-site.stderr rename to tests/ui/supertrait-shadowing/definition-site.stderr diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs b/tests/ui/supertrait-shadowing/false-subtrait-after-inference.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.rs rename to tests/ui/supertrait-shadowing/false-subtrait-after-inference.rs diff --git a/tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr b/tests/ui/supertrait-shadowing/false-subtrait-after-inference.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/false-subtrait-after-inference.stderr rename to tests/ui/supertrait-shadowing/false-subtrait-after-inference.stderr diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.rs rename to tests/ui/supertrait-shadowing/no-common-ancestor-2.rs diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/no-common-ancestor-2.stderr rename to tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs b/tests/ui/supertrait-shadowing/no-common-ancestor.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/no-common-ancestor.rs rename to tests/ui/supertrait-shadowing/no-common-ancestor.rs diff --git a/tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/no-common-ancestor.stderr rename to tests/ui/supertrait-shadowing/no-common-ancestor.stderr diff --git a/tests/ui/methods/supertrait-shadowing/out-of-scope.rs b/tests/ui/supertrait-shadowing/out-of-scope.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/out-of-scope.rs rename to tests/ui/supertrait-shadowing/out-of-scope.rs diff --git a/tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs b/tests/ui/supertrait-shadowing/trivially-false-subtrait.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/trivially-false-subtrait.rs rename to tests/ui/supertrait-shadowing/trivially-false-subtrait.rs diff --git a/tests/ui/methods/supertrait-shadowing/type-dependent.rs b/tests/ui/supertrait-shadowing/type-dependent.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/type-dependent.rs rename to tests/ui/supertrait-shadowing/type-dependent.rs diff --git a/tests/ui/methods/supertrait-shadowing/unstable.off_normal.stderr b/tests/ui/supertrait-shadowing/unstable.off_normal.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.off_normal.stderr rename to tests/ui/supertrait-shadowing/unstable.off_normal.stderr diff --git a/tests/ui/methods/supertrait-shadowing/unstable.off_shadowing.stderr b/tests/ui/supertrait-shadowing/unstable.off_shadowing.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.off_shadowing.stderr rename to tests/ui/supertrait-shadowing/unstable.off_shadowing.stderr diff --git a/tests/ui/methods/supertrait-shadowing/unstable.on_normal.stderr b/tests/ui/supertrait-shadowing/unstable.on_normal.stderr similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.on_normal.stderr rename to tests/ui/supertrait-shadowing/unstable.on_normal.stderr diff --git a/tests/ui/methods/supertrait-shadowing/unstable.rs b/tests/ui/supertrait-shadowing/unstable.rs similarity index 100% rename from tests/ui/methods/supertrait-shadowing/unstable.rs rename to tests/ui/supertrait-shadowing/unstable.rs From af3eaeeedd1812692940f6d8947ad3573680c432 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 4 Jun 2026 17:03:02 +0100 Subject: [PATCH 59/77] Address review feedback for tests --- tests/ui/README.md | 4 + tests/ui/supertrait-shadowing/assoc-const.rs | 15 ++- tests/ui/supertrait-shadowing/assoc-const2.rs | 32 ------- .../assoc-const2.run.stdout | 2 - .../supertrait-shadowing/assoc-type-fail.rs | 47 +++++++++ .../assoc-type-fail.stderr | 37 ++++++++ .../assoc-type-predicates.rs | 45 +++++++++ .../assoc-type-predicates.stderr | 32 +++++++ tests/ui/supertrait-shadowing/assoc-type.rs | 30 +++--- .../assoc-type.run.stdout | 4 - .../supertrait-shadowing/common-ancestor-2.rs | 32 ++++++- .../common-ancestor-2.stderr | 46 +++++++-- .../supertrait-shadowing/common-ancestor-3.rs | 41 +++++++- .../common-ancestor-3.stderr | 86 +++++++++++++++-- .../supertrait-shadowing/common-ancestor.rs | 25 ++++- .../common-ancestor.stderr | 40 ++++++-- .../supertrait-shadowing/definition-site.rs | 10 ++ .../definition-site.stderr | 60 +++++++++++- .../no-common-ancestor-2.rs | 39 +++++++- .../no-common-ancestor-2.stderr | 95 +++++++++++++++++-- .../no-common-ancestor.rs | 25 ++++- .../no-common-ancestor.stderr | 59 +++++++++++- tests/ui/supertrait-shadowing/out-of-scope.rs | 23 ++++- .../ui/supertrait-shadowing/type-dependent.rs | 29 +++++- 24 files changed, 744 insertions(+), 114 deletions(-) delete mode 100644 tests/ui/supertrait-shadowing/assoc-const2.rs delete mode 100644 tests/ui/supertrait-shadowing/assoc-const2.run.stdout create mode 100644 tests/ui/supertrait-shadowing/assoc-type-fail.rs create mode 100644 tests/ui/supertrait-shadowing/assoc-type-fail.stderr create mode 100644 tests/ui/supertrait-shadowing/assoc-type-predicates.rs create mode 100644 tests/ui/supertrait-shadowing/assoc-type-predicates.stderr delete mode 100644 tests/ui/supertrait-shadowing/assoc-type.run.stdout diff --git a/tests/ui/README.md b/tests/ui/README.md index 6ffef1a1cd699..d342f393d0550 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1351,6 +1351,10 @@ Generic collection of tests for suggestions, when no more specific directories a **FIXME**: Some overlap with `tests/ui/did_you_mean/`, that directory should probably be moved under here. +## `tests/ui/supertrait-shadowing/` + +Tests for supertrait item shadowing (RFC 3624). + ## `tests/ui/svh/`: Strict Version Hash Tests on the *Strict Version Hash* (SVH, also known as the "crate hash"). diff --git a/tests/ui/supertrait-shadowing/assoc-const.rs b/tests/ui/supertrait-shadowing/assoc-const.rs index 01d045b9fb74f..be0d990284b0c 100644 --- a/tests/ui/supertrait-shadowing/assoc-const.rs +++ b/tests/ui/supertrait-shadowing/assoc-const.rs @@ -1,6 +1,7 @@ //@ run-pass #![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] #![allow(dead_code)] trait A { @@ -11,12 +12,20 @@ impl A for T { } trait B: A { - const CONST: i32; + type const CONST: i32; } impl B for T { - const CONST: i32 = 2; + type const CONST: i32 = 2; } +trait C: B {} +impl C for T {} + fn main() { - assert_eq!(i32::CONST, 2) + assert_eq!(i32::CONST, 2); + generic::(); +} + +fn generic>() { + assert_eq!(T::CONST, 2); } diff --git a/tests/ui/supertrait-shadowing/assoc-const2.rs b/tests/ui/supertrait-shadowing/assoc-const2.rs deleted file mode 100644 index ebd0875eac8ea..0000000000000 --- a/tests/ui/supertrait-shadowing/assoc-const2.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@ run-pass -//@ check-run-results - -#![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] -#![allow(dead_code)] - -trait A { - const CONST: i32; -} -impl A for T { - const CONST: i32 = 1; -} - -trait B: A { - type const CONST: i32; -} -impl B for T { - type const CONST: i32 = 2; -} - -trait C: B {} -impl C for T {} - -fn main() { - println!("{}", i32::CONST); - generic::(); -} - -fn generic>() { - println!("{}", T::CONST); -} diff --git a/tests/ui/supertrait-shadowing/assoc-const2.run.stdout b/tests/ui/supertrait-shadowing/assoc-const2.run.stdout deleted file mode 100644 index 51993f072d583..0000000000000 --- a/tests/ui/supertrait-shadowing/assoc-const2.run.stdout +++ /dev/null @@ -1,2 +0,0 @@ -2 -2 diff --git a/tests/ui/supertrait-shadowing/assoc-type-fail.rs b/tests/ui/supertrait-shadowing/assoc-type-fail.rs new file mode 100644 index 0000000000000..5df4edb7e96e2 --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-fail.rs @@ -0,0 +1,47 @@ +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +use std::mem::size_of; + +trait A { + type Assoc; +} +impl A for X { + type Assoc = i8; +} + +trait B: A { + type Assoc; +} +impl B for X { + type Assoc = i16; +} + +trait C: B {} +impl C for X {} + +fn main() { + b_unbound::(); + c_unbound::(); + + b_assoc_is_a::(); + //~^ ERROR type mismatch resolving `::Assoc == i8` + c_assoc_is_a::(); + //~^ ERROR type mismatch resolving `::Assoc == i8` +} + +fn b_unbound() { + let _ = size_of::(); +} + +fn c_unbound() { + let _ = size_of::(); +} + +fn b_assoc_is_a>() { + let _ = size_of::(); +} + +fn c_assoc_is_a>() { + let _ = size_of::(); +} diff --git a/tests/ui/supertrait-shadowing/assoc-type-fail.stderr b/tests/ui/supertrait-shadowing/assoc-type-fail.stderr new file mode 100644 index 0000000000000..36a9bd082aaf6 --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-fail.stderr @@ -0,0 +1,37 @@ +error[E0271]: type mismatch resolving `::Assoc == i8` + --> $DIR/assoc-type-fail.rs:27:20 + | +LL | b_assoc_is_a::(); + | ^^^ type mismatch resolving `::Assoc == i8` + | +note: expected this to be `i8` + --> $DIR/assoc-type-fail.rs:17:18 + | +LL | type Assoc = i16; + | ^^^ +note: required by a bound in `b_assoc_is_a` + --> $DIR/assoc-type-fail.rs:41:22 + | +LL | fn b_assoc_is_a>() { + | ^^^^^^^^^^ required by this bound in `b_assoc_is_a` + +error[E0271]: type mismatch resolving `::Assoc == i8` + --> $DIR/assoc-type-fail.rs:29:20 + | +LL | c_assoc_is_a::(); + | ^^^ type mismatch resolving `::Assoc == i8` + | +note: expected this to be `i8` + --> $DIR/assoc-type-fail.rs:17:18 + | +LL | type Assoc = i16; + | ^^^ +note: required by a bound in `c_assoc_is_a` + --> $DIR/assoc-type-fail.rs:45:22 + | +LL | fn c_assoc_is_a>() { + | ^^^^^^^^^^ required by this bound in `c_assoc_is_a` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/supertrait-shadowing/assoc-type-predicates.rs b/tests/ui/supertrait-shadowing/assoc-type-predicates.rs new file mode 100644 index 0000000000000..55d2b84a50f9a --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-predicates.rs @@ -0,0 +1,45 @@ +//@ normalize-stderr: "assoc_type_predicates\[[^\]]+\]" -> "assoc_type_predicates[HASH]" + +#![feature(rustc_attrs)] +#![feature(supertrait_item_shadowing)] +#![allow(dead_code)] + +trait A { + type Assoc; +} +impl A for T { + type Assoc = i8; +} + +trait B: A { + type Assoc; +} +impl B for T { + type Assoc = i16; +} + +trait C: B {} +impl C for T {} + +#[rustc_dump_predicates] +fn a_bound>() {} +//~^ ERROR rustc_dump_predicates +//~| NOTE TraitPredicate( +//~| NOTE TraitPredicate( +//~| NOTE A::Assoc + +#[rustc_dump_predicates] +fn b_bound>() {} +//~^ ERROR rustc_dump_predicates +//~| NOTE TraitPredicate( +//~| NOTE TraitPredicate( +//~| NOTE B::Assoc + +#[rustc_dump_predicates] +fn c_bound>() {} +//~^ ERROR rustc_dump_predicates +//~| NOTE TraitPredicate( +//~| NOTE TraitPredicate( +//~| NOTE B::Assoc + +fn main() {} diff --git a/tests/ui/supertrait-shadowing/assoc-type-predicates.stderr b/tests/ui/supertrait-shadowing/assoc-type-predicates.stderr new file mode 100644 index 0000000000000..be765e737a6e1 --- /dev/null +++ b/tests/ui/supertrait-shadowing/assoc-type-predicates.stderr @@ -0,0 +1,32 @@ +error: rustc_dump_predicates + --> $DIR/assoc-type-predicates.rs:25:1 + | +LL | fn a_bound>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(Alias { kind: ProjectionTy { def_id: DefId(0:4 ~ assoc_type_predicates[HASH]::A::Assoc) }, args: [T/#0], .. }, Term::Ty(i8)), bound_vars: [] } + +error: rustc_dump_predicates + --> $DIR/assoc-type-predicates.rs:32:1 + | +LL | fn b_bound>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(Alias { kind: ProjectionTy { def_id: DefId(0:9 ~ assoc_type_predicates[HASH]::B::Assoc) }, args: [T/#0], .. }, Term::Ty(i16)), bound_vars: [] } + +error: rustc_dump_predicates + --> $DIR/assoc-type-predicates.rs:39:1 + | +LL | fn c_bound>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(Alias { kind: ProjectionTy { def_id: DefId(0:9 ~ assoc_type_predicates[HASH]::B::Assoc) }, args: [T/#0], .. }, Term::Ty(i16)), bound_vars: [] } + +error: aborting due to 3 previous errors + diff --git a/tests/ui/supertrait-shadowing/assoc-type.rs b/tests/ui/supertrait-shadowing/assoc-type.rs index 7434fa7523119..9e9799397c571 100644 --- a/tests/ui/supertrait-shadowing/assoc-type.rs +++ b/tests/ui/supertrait-shadowing/assoc-type.rs @@ -7,17 +7,17 @@ use std::mem::size_of; trait A { - type T; + type Assoc; } impl A for T { - type T = i8; + type Assoc = i8; } trait B: A { - type T; + type Assoc; } impl B for T { - type T = i16; + type Assoc = i16; } trait C: B {} @@ -28,20 +28,26 @@ fn main() { generic2::(); generic3::(); generic4::(); + generic5::(); } -fn generic() { - println!("{}", size_of::()); +fn generic() { + assert_eq!(size_of::(), 2); } -fn generic2>() { - println!("{}", size_of::()); +fn generic2>() { + assert_eq!(size_of::(), 1); } -fn generic3>() { - println!("{}", size_of::()); +fn generic3>() { + assert_eq!(size_of::(), 2); } -fn generic4>() { - println!("{}", size_of::()); +fn generic4>() { + assert_eq!(size_of::(), 2); +} + +fn generic5() { + assert_eq!(size_of::<::Assoc>(), 1); + assert_eq!(size_of::<::Assoc>(), 2); } diff --git a/tests/ui/supertrait-shadowing/assoc-type.run.stdout b/tests/ui/supertrait-shadowing/assoc-type.run.stdout deleted file mode 100644 index 6f9071418f37e..0000000000000 --- a/tests/ui/supertrait-shadowing/assoc-type.run.stdout +++ /dev/null @@ -1,4 +0,0 @@ -2 -1 -2 -2 diff --git a/tests/ui/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/supertrait-shadowing/common-ancestor-2.rs index ce56c25df19ea..908c5d2bf2199 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-2.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.rs @@ -1,33 +1,59 @@ //@ run-pass #![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] #![warn(resolving_to_items_shadowing_supertrait_items)] #![warn(shadowing_supertrait_items)] #![allow(dead_code)] +use std::mem::size_of; + trait A { fn hello(&self) -> &'static str { "A" } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl A for T {} trait B { fn hello(&self) -> &'static str { "B" } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; } -impl B for T {} trait C: A + B { fn hello(&self) -> &'static str { //~^ WARN trait item `hello` from `C` shadows identically named item "C" } + type Assoc; + //~^ WARN trait item `Assoc` from `C` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `C` shadows identically named item +} +impl C for T { + type Assoc = i32; + type const CONST: i32 = 3; } -impl C for T {} fn main() { assert_eq!(().hello(), "C"); //~^ WARN trait item `hello` from `C` shadows identically named item from supertrait + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 4); + assert_eq!(T::CONST, 3); } diff --git a/tests/ui/supertrait-shadowing/common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr index b0f61b46b6911..646726b835041 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-2.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr @@ -1,11 +1,11 @@ warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:23:5 + --> $DIR/common-ancestor-2.rs:36:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-2.rs:9:5 + --> $DIR/common-ancestor-2.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,24 +13,54 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor-2.rs:5:9 + --> $DIR/common-ancestor-2.rs:6:9 | LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: trait item `Assoc` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-2.rs:40:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-2.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-2.rs:42:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-2.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:31:19 + --> $DIR/common-ancestor-2.rs:51:19 | LL | assert_eq!(().hello(), "C"); | ^^^^^ | note: item from `C` shadows a supertrait item - --> $DIR/common-ancestor-2.rs:23:5 + --> $DIR/common-ancestor-2.rs:36:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: items from several supertraits are shadowed: `A` and `B` - --> $DIR/common-ancestor-2.rs:9:5 + --> $DIR/common-ancestor-2.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,10 +68,10 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor-2.rs:4:9 + --> $DIR/common-ancestor-2.rs:5:9 | LL | #![warn(resolving_to_items_shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 2 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/supertrait-shadowing/common-ancestor-3.rs index b29f3c8d014ec..ade23ca88aec2 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-3.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.rs @@ -1,31 +1,51 @@ //@ run-pass #![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] #![warn(resolving_to_items_shadowing_supertrait_items)] #![warn(shadowing_supertrait_items)] #![allow(dead_code)] +use std::mem::size_of; + trait A { fn hello(&self) -> &'static str { "A" } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl A for T {} trait B { fn hello(&self) -> &'static str { "B" } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; } -impl B for T {} trait C: A + B { fn hello(&self) -> &'static str { //~^ WARN trait item `hello` from `C` shadows identically named item "C" } + type Assoc; + //~^ WARN trait item `Assoc` from `C` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `C` shadows identically named item +} +impl C for T { + type Assoc = i32; + type const CONST: i32 = 3; } -impl C for T {} // `D` extends `C` which extends `B` and `A` @@ -34,10 +54,23 @@ trait D: C { //~^ WARN trait item `hello` from `D` shadows identically named item "D" } + type Assoc; + //~^ WARN trait item `Assoc` from `D` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `D` shadows identically named item +} +impl D for T { + type Assoc = i64; + type const CONST: i32 = 4; } -impl D for T {} fn main() { assert_eq!(().hello(), "D"); //~^ WARN trait item `hello` from `D` shadows identically named item from supertrait + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 8); + assert_eq!(T::CONST, 4); } diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr index 28fe7f72f94c3..62132832da4ba 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-3.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr @@ -1,11 +1,11 @@ warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:23:5 + --> $DIR/common-ancestor-3.rs:36:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-3.rs:9:5 + --> $DIR/common-ancestor-3.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,19 +13,49 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor-3.rs:5:9 + --> $DIR/common-ancestor-3.rs:6:9 | LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: trait item `Assoc` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:40:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-3.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `C` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:42:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `B` and `A` + --> $DIR/common-ancestor-3.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + warning: trait item `hello` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:33:5 + --> $DIR/common-ancestor-3.rs:53:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `C`, `B`, and `A` - --> $DIR/common-ancestor-3.rs:9:5 + --> $DIR/common-ancestor-3.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,19 +66,55 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: trait item `Assoc` from `D` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:57:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `C`, `B`, and `A` + --> $DIR/common-ancestor-3.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `D` shadows identically named item from supertrait + --> $DIR/common-ancestor-3.rs:59:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `C`, `B`, and `A` + --> $DIR/common-ancestor-3.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + warning: trait item `hello` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:41:19 + --> $DIR/common-ancestor-3.rs:68:19 | LL | assert_eq!(().hello(), "D"); | ^^^^^ | note: item from `D` shadows a supertrait item - --> $DIR/common-ancestor-3.rs:33:5 + --> $DIR/common-ancestor-3.rs:53:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: items from several supertraits are shadowed: `A`, `B`, and `C` - --> $DIR/common-ancestor-3.rs:9:5 + --> $DIR/common-ancestor-3.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,10 +125,10 @@ LL | fn hello(&self) -> &'static str { LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor-3.rs:4:9 + --> $DIR/common-ancestor-3.rs:5:9 | LL | #![warn(resolving_to_items_shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 3 warnings emitted +warning: 7 warnings emitted diff --git a/tests/ui/supertrait-shadowing/common-ancestor.rs b/tests/ui/supertrait-shadowing/common-ancestor.rs index b288d6e22b8c3..903f85957870b 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor.rs @@ -1,26 +1,47 @@ //@ run-pass #![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] #![warn(resolving_to_items_shadowing_supertrait_items)] #![warn(shadowing_supertrait_items)] #![allow(dead_code)] +use std::mem::size_of; + trait A { fn hello(&self) -> &'static str { "A" } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl A for T {} trait B: A { fn hello(&self) -> &'static str { //~^ WARN trait item `hello` from `B` shadows identically named item "B" } + type Assoc; + //~^ WARN trait item `Assoc` from `B` shadows identically named item + type const CONST: i32; + //~^ WARN trait item `CONST` from `B` shadows identically named item +} +impl B for T { + type Assoc = i16; + type const CONST: i32 = 2; } -impl B for T {} fn main() { assert_eq!(().hello(), "B"); //~^ WARN trait item `hello` from `B` shadows identically named item from supertrait + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 2); + assert_eq!(T::CONST, 2); } diff --git a/tests/ui/supertrait-shadowing/common-ancestor.stderr b/tests/ui/supertrait-shadowing/common-ancestor.stderr index 9afedeab5e2c2..9b13537cf800c 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor.stderr @@ -1,41 +1,65 @@ warning: trait item `hello` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:16:5 + --> $DIR/common-ancestor.rs:24:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:9:5 + --> $DIR/common-ancestor.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor.rs:5:9 + --> $DIR/common-ancestor.rs:6:9 | LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: trait item `Assoc` from `B` shadows identically named item from supertrait + --> $DIR/common-ancestor.rs:28:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: item from `A` is shadowed by a subtrait item + --> $DIR/common-ancestor.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + +warning: trait item `CONST` from `B` shadows identically named item from supertrait + --> $DIR/common-ancestor.rs:30:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: item from `A` is shadowed by a subtrait item + --> $DIR/common-ancestor.rs:16:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + warning: trait item `hello` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:24:19 + --> $DIR/common-ancestor.rs:39:19 | LL | assert_eq!(().hello(), "B"); | ^^^^^ | note: item from `B` shadows a supertrait item - --> $DIR/common-ancestor.rs:16:5 + --> $DIR/common-ancestor.rs:24:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:9:5 + --> $DIR/common-ancestor.rs:12:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/common-ancestor.rs:4:9 + --> $DIR/common-ancestor.rs:5:9 | LL | #![warn(resolving_to_items_shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 2 warnings emitted +warning: 4 warnings emitted diff --git a/tests/ui/supertrait-shadowing/definition-site.rs b/tests/ui/supertrait-shadowing/definition-site.rs index 248df032736f6..3309ee97e9f00 100644 --- a/tests/ui/supertrait-shadowing/definition-site.rs +++ b/tests/ui/supertrait-shadowing/definition-site.rs @@ -3,16 +3,26 @@ trait SuperSuper { fn method(); + const CONST: i32; + type Assoc; } trait Super: SuperSuper { fn method(); //~^ ERROR trait item `method` from `Super` shadows identically named item + const CONST: i32; + //~^ ERROR trait item `CONST` from `Super` shadows identically named item + type Assoc; + //~^ ERROR trait item `Assoc` from `Super` shadows identically named item } trait Sub: Super { fn method(); //~^ ERROR trait item `method` from `Sub` shadows identically named item + const CONST: i32; + //~^ ERROR trait item `CONST` from `Sub` shadows identically named item + type Assoc; + //~^ ERROR trait item `Assoc` from `Sub` shadows identically named item } fn main() {} diff --git a/tests/ui/supertrait-shadowing/definition-site.stderr b/tests/ui/supertrait-shadowing/definition-site.stderr index 1e35a753a9ebc..faf01cc711c6a 100644 --- a/tests/ui/supertrait-shadowing/definition-site.stderr +++ b/tests/ui/supertrait-shadowing/definition-site.stderr @@ -1,5 +1,5 @@ error: trait item `method` from `Super` shadows identically named item from supertrait - --> $DIR/definition-site.rs:9:5 + --> $DIR/definition-site.rs:11:5 | LL | fn method(); | ^^^^^^^^^^^^ @@ -15,8 +15,32 @@ note: the lint level is defined here LL | #![deny(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: trait item `CONST` from `Super` shadows identically named item from supertrait + --> $DIR/definition-site.rs:13:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + | +note: item from `SuperSuper` is shadowed by a subtrait item + --> $DIR/definition-site.rs:6:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + +error: trait item `Assoc` from `Super` shadows identically named item from supertrait + --> $DIR/definition-site.rs:15:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: item from `SuperSuper` is shadowed by a subtrait item + --> $DIR/definition-site.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + error: trait item `method` from `Sub` shadows identically named item from supertrait - --> $DIR/definition-site.rs:14:5 + --> $DIR/definition-site.rs:20:5 | LL | fn method(); | ^^^^^^^^^^^^ @@ -30,5 +54,35 @@ LL | fn method(); LL | fn method(); | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: trait item `CONST` from `Sub` shadows identically named item from supertrait + --> $DIR/definition-site.rs:22:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `Super` and `SuperSuper` + --> $DIR/definition-site.rs:6:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +... +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ + +error: trait item `Assoc` from `Sub` shadows identically named item from supertrait + --> $DIR/definition-site.rs:24:5 + | +LL | type Assoc; + | ^^^^^^^^^^ + | +note: items from several supertraits are shadowed: `Super` and `SuperSuper` + --> $DIR/definition-site.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^ +... +LL | type Assoc; + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs index b49476c7a4f68..957aabf5a51f8 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs @@ -1,25 +1,43 @@ #![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] + +use std::mem::size_of; trait A { fn hello(&self) -> &'static str { "A" } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl A for T {} trait B { fn hello(&self) -> &'static str { "B" } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; } -impl B for T {} trait C: A + B { fn hello(&self) -> &'static str { "C" } + type Assoc; + type const CONST: i32; +} +impl C for T { + type Assoc = i32; + type const CONST: i32 = 3; } -impl C for T {} // Since `D` is not a subtrait of `C`, // we have no obvious lower bound. @@ -28,10 +46,23 @@ trait D: B { fn hello(&self) -> &'static str { "D" } + type Assoc; + type const CONST: i32; +} +impl D for T { + type Assoc = i64; + type const CONST: i32 = 4; } -impl D for T {} fn main() { ().hello(); //~^ ERROR multiple applicable items in scope + check::<()>(); +} + +fn check() { + let _ = size_of::(); + //~^ ERROR ambiguous associated type `Assoc` in bounds of `T` + let _ = T::CONST; + //~^ ERROR multiple applicable items in scope } diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr index 745f61d00d660..987adcfbbe959 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr @@ -1,26 +1,26 @@ error[E0034]: multiple applicable items in scope - --> $DIR/no-common-ancestor-2.rs:35:8 + --> $DIR/no-common-ancestor-2.rs:58:8 | LL | ().hello(); | ^^^^^ multiple `hello` found | note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/no-common-ancestor-2.rs:4:5 + --> $DIR/no-common-ancestor-2.rs:7:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/no-common-ancestor-2.rs:11:5 + --> $DIR/no-common-ancestor-2.rs:19:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #3 is defined in an impl of the trait `C` for the type `T` - --> $DIR/no-common-ancestor-2.rs:18:5 + --> $DIR/no-common-ancestor-2.rs:31:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #4 is defined in an impl of the trait `D` for the type `T` - --> $DIR/no-common-ancestor-2.rs:28:5 + --> $DIR/no-common-ancestor-2.rs:46:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,6 +45,87 @@ LL - ().hello(); LL + D::hello(&()); | -error: aborting due to 1 previous error +error[E0221]: ambiguous associated type `Assoc` in bounds of `T` + --> $DIR/no-common-ancestor-2.rs:64:23 + | +LL | type Assoc; + | ---------- ambiguous `Assoc` from `A` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `B` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `C` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `D` +... +LL | let _ = size_of::(); + | ^^^^^^^^ ambiguous associated type `Assoc` + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | + +error[E0034]: multiple applicable items in scope + --> $DIR/no-common-ancestor-2.rs:66:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/no-common-ancestor-2.rs:11:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/no-common-ancestor-2.rs:23:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +note: candidate #3 is defined in the trait `C` + --> $DIR/no-common-ancestor-2.rs:35:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ +note: candidate #4 is defined in the trait `D` + --> $DIR/no-common-ancestor-2.rs:50:5 + | +LL | type const CONST: i32; + | ^^^^^^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0034`. +Some errors have detailed explanations: E0034, E0221. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor.rs b/tests/ui/supertrait-shadowing/no-common-ancestor.rs index 03c822eb7375e..73209c015f8f5 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor.rs +++ b/tests/ui/supertrait-shadowing/no-common-ancestor.rs @@ -1,20 +1,41 @@ #![feature(supertrait_item_shadowing)] +#![feature(min_generic_const_args)] + +use std::mem::size_of; trait A { fn hello(&self) -> &'static str { "A" } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl A for T {} trait B { fn hello(&self) -> &'static str { "B" } + type Assoc; + const CONST: i32; +} +impl B for T { + type Assoc = i16; + const CONST: i32 = 2; } -impl B for T {} fn main() { ().hello(); //~^ ERROR multiple applicable items in scope + check::<()>(); +} + +fn check() { + let _ = size_of::(); + //~^ ERROR ambiguous associated type `Assoc` in bounds of `T` + let _ = T::CONST; + //~^ ERROR multiple applicable items in scope } diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor.stderr index 29cf7ff1dbb11..78fd8f4670577 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor.stderr +++ b/tests/ui/supertrait-shadowing/no-common-ancestor.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/no-common-ancestor.rs:18:8 + --> $DIR/no-common-ancestor.rs:31:8 | LL | ().hello(); | ^^^^^ multiple `hello` found | note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/no-common-ancestor.rs:4:5 + --> $DIR/no-common-ancestor.rs:7:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/no-common-ancestor.rs:11:5 + --> $DIR/no-common-ancestor.rs:19:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,6 +25,55 @@ LL - ().hello(); LL + B::hello(&()); | -error: aborting due to 1 previous error +error[E0221]: ambiguous associated type `Assoc` in bounds of `T` + --> $DIR/no-common-ancestor.rs:37:23 + | +LL | type Assoc; + | ---------- ambiguous `Assoc` from `A` +... +LL | type Assoc; + | ---------- ambiguous `Assoc` from `B` +... +LL | let _ = size_of::(); + | ^^^^^^^^ ambiguous associated type `Assoc` + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | +help: use fully-qualified syntax to disambiguate + | +LL - let _ = size_of::(); +LL + let _ = size_of::<::Assoc>(); + | + +error[E0034]: multiple applicable items in scope + --> $DIR/no-common-ancestor.rs:39:16 + | +LL | let _ = T::CONST; + | ^^^^^ multiple `CONST` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/no-common-ancestor.rs:11:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/no-common-ancestor.rs:23:5 + | +LL | const CONST: i32; + | ^^^^^^^^^^^^^^^^ +help: use fully-qualified syntax to disambiguate + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | +LL - let _ = T::CONST; +LL + let _ = ::CONST; + | + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0034`. +Some errors have detailed explanations: E0034, E0221. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/supertrait-shadowing/out-of-scope.rs b/tests/ui/supertrait-shadowing/out-of-scope.rs index 4112634399b78..7b2322843f1c3 100644 --- a/tests/ui/supertrait-shadowing/out-of-scope.rs +++ b/tests/ui/supertrait-shadowing/out-of-scope.rs @@ -1,23 +1,42 @@ //@ run-pass +#![feature(min_generic_const_args)] #![allow(dead_code)] +use std::mem::size_of; + mod out_of_scope { pub trait Subtrait: super::Supertrait { fn hello(&self) -> &'static str { "subtrait" } + type Assoc; + type const CONST: i32; + } + impl Subtrait for T { + type Assoc = i16; + type const CONST: i32 = 2; } - impl Subtrait for T {} } trait Supertrait { fn hello(&self) -> &'static str { "supertrait" } + type Assoc; + const CONST: i32; +} +impl Supertrait for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl Supertrait for T {} fn main() { assert_eq!(().hello(), "supertrait"); + check::<()>(); +} + +fn check() { + assert_eq!(size_of::(), 1); + assert_eq!(T::CONST, 1); } diff --git a/tests/ui/supertrait-shadowing/type-dependent.rs b/tests/ui/supertrait-shadowing/type-dependent.rs index 4a5af1d598812..75272d101dd29 100644 --- a/tests/ui/supertrait-shadowing/type-dependent.rs +++ b/tests/ui/supertrait-shadowing/type-dependent.rs @@ -1,28 +1,51 @@ //@ run-pass -// Makes sure we can shadow with type-dependent method syntax. +// Makes sure we can shadow with type-dependent associated item syntax. +#![feature(min_generic_const_args)] #![feature(supertrait_item_shadowing)] #![allow(dead_code)] +use std::mem::size_of; + trait A { fn hello() -> &'static str { "A" } + type Assoc; + const CONST: i32; +} +impl A for T { + type Assoc = i8; + const CONST: i32 = 1; } -impl A for T {} trait B: A { fn hello() -> &'static str { "B" } + type Assoc; + type const CONST: i32; +} +impl B for T { + type Assoc = i16; + type const CONST: i32 = 2; } -impl B for T {} fn foo() -> &'static str { T::hello() } +fn assoc() -> usize { + size_of::() +} + +fn konst() -> i32 { + T::CONST +} + fn main() { assert_eq!(foo::<()>(), "B"); + assert_eq!(assoc::<()>(), 2); + assert_eq!(konst::<()>(), 2); } From 2592b4176d62f5310957cc5595d2ab0747326d3c Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Fri, 26 Jun 2026 22:34:26 +0100 Subject: [PATCH 60/77] Add test to confirm usage of unstable foreign type error Signed-off-by: Emmanuel Ugwu --- tests/ui/lint/auxiliary/lint_stability.rs | 6 ++++++ tests/ui/lint/lint-stability.rs | 7 +++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/ui/lint/auxiliary/lint_stability.rs b/tests/ui/lint/auxiliary/lint_stability.rs index 99c29dcdda677..bc2d47aebbc29 100644 --- a/tests/ui/lint/auxiliary/lint_stability.rs +++ b/tests/ui/lint/auxiliary/lint_stability.rs @@ -1,5 +1,6 @@ #![crate_name="lint_stability"] #![crate_type = "lib"] +#![feature(extern_types)] #![feature(staged_api)] #![feature(associated_type_defaults)] #![stable(feature = "lint_stability", since = "1.0.0")] @@ -186,3 +187,8 @@ macro_rules! macro_test_arg { macro_rules! macro_test_arg_nested { ($func:ident) => (macro_test_arg!($func())); } + +extern "C" { + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub type UnstableForeignType; +} diff --git a/tests/ui/lint/lint-stability.rs b/tests/ui/lint/lint-stability.rs index 21009b1e61db4..c8712397189c7 100644 --- a/tests/ui/lint/lint-stability.rs +++ b/tests/ui/lint/lint-stability.rs @@ -9,10 +9,6 @@ #![feature(extern_types)] #![stable(feature = "rust1", since = "1.0.0")] -extern "C" { - #[unstable(feature = "fn_static", issue = "none")] - type Ty; -} #[macro_use] extern crate lint_stability; @@ -22,6 +18,9 @@ mod cross_crate { use lint_stability::*; + fn test_foreign_type(_: &mut UnstableForeignType) { //~ ERROR use of unstable library feature + } + fn test() { type Foo = MethodTester; let foo = MethodTester; From ca28237682237165e6313fd77d7cb0bd1ba5ae0e Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 27 Jun 2026 03:00:38 +0200 Subject: [PATCH 61/77] move batch --- .../resolve-method-with-missing-assoc-type.rs} | 0 .../resolve-method-with-missing-assoc-type.stderr} | 0 .../{issues/issue-27949.rs => binop/binop-subtyping-lifetimes.rs} | 0 .../issue-27889.rs => borrowck/enum-variants-share-field-name.rs} | 0 .../clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs} | 0 .../derive-copy-clone-non-copy-field-diagnostic.stderr} | 0 .../dropflag-reinit-in-loop.rs} | 0 .../region-leak-rc-and-mut-ptr.rs} | 0 .../lifetime-errors/trait-method-return-lifetime-mismatch.rs} | 0 .../lifetime-errors/trait-method-return-lifetime-mismatch.stderr} | 0 .../issue-2761.rs => macros/assert-with-custom-message.rs} | 0 .../issue-27815.rs => structs/non-struct-in-struct-position.rs} | 0 .../non-struct-in-struct-position.stderr} | 0 .../issue-27842.rs => tuple/tuple-bracket-index-suggest-dot.rs} | 0 .../tuple-bracket-index-suggest-dot.stderr} | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-28344.rs => associated-types/resolve-method-with-missing-assoc-type.rs} (100%) rename tests/ui/{issues/issue-28344.stderr => associated-types/resolve-method-with-missing-assoc-type.stderr} (100%) rename tests/ui/{issues/issue-27949.rs => binop/binop-subtyping-lifetimes.rs} (100%) rename tests/ui/{issues/issue-27889.rs => borrowck/enum-variants-share-field-name.rs} (100%) rename tests/ui/{issues/issue-27340.rs => derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs} (100%) rename tests/ui/{issues/issue-27340.stderr => derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr} (100%) rename tests/ui/{issues/issue-27401-dropflag-reinit.rs => drop/dropflag-reinit-in-loop.rs} (100%) rename tests/ui/{issues/issue-28279.rs => higher-ranked/region-leak-rc-and-mut-ptr.rs} (100%) rename tests/ui/{issues/issue-27942.rs => lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs} (100%) rename tests/ui/{issues/issue-27942.stderr => lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr} (100%) rename tests/ui/{issues/issue-2761.rs => macros/assert-with-custom-message.rs} (100%) rename tests/ui/{issues/issue-27815.rs => structs/non-struct-in-struct-position.rs} (100%) rename tests/ui/{issues/issue-27815.stderr => structs/non-struct-in-struct-position.stderr} (100%) rename tests/ui/{issues/issue-27842.rs => tuple/tuple-bracket-index-suggest-dot.rs} (100%) rename tests/ui/{issues/issue-27842.stderr => tuple/tuple-bracket-index-suggest-dot.stderr} (100%) diff --git a/tests/ui/issues/issue-28344.rs b/tests/ui/associated-types/resolve-method-with-missing-assoc-type.rs similarity index 100% rename from tests/ui/issues/issue-28344.rs rename to tests/ui/associated-types/resolve-method-with-missing-assoc-type.rs diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/associated-types/resolve-method-with-missing-assoc-type.stderr similarity index 100% rename from tests/ui/issues/issue-28344.stderr rename to tests/ui/associated-types/resolve-method-with-missing-assoc-type.stderr diff --git a/tests/ui/issues/issue-27949.rs b/tests/ui/binop/binop-subtyping-lifetimes.rs similarity index 100% rename from tests/ui/issues/issue-27949.rs rename to tests/ui/binop/binop-subtyping-lifetimes.rs diff --git a/tests/ui/issues/issue-27889.rs b/tests/ui/borrowck/enum-variants-share-field-name.rs similarity index 100% rename from tests/ui/issues/issue-27889.rs rename to tests/ui/borrowck/enum-variants-share-field-name.rs diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs similarity index 100% rename from tests/ui/issues/issue-27340.rs rename to tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr similarity index 100% rename from tests/ui/issues/issue-27340.stderr rename to tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr diff --git a/tests/ui/issues/issue-27401-dropflag-reinit.rs b/tests/ui/drop/dropflag-reinit-in-loop.rs similarity index 100% rename from tests/ui/issues/issue-27401-dropflag-reinit.rs rename to tests/ui/drop/dropflag-reinit-in-loop.rs diff --git a/tests/ui/issues/issue-28279.rs b/tests/ui/higher-ranked/region-leak-rc-and-mut-ptr.rs similarity index 100% rename from tests/ui/issues/issue-28279.rs rename to tests/ui/higher-ranked/region-leak-rc-and-mut-ptr.rs diff --git a/tests/ui/issues/issue-27942.rs b/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs similarity index 100% rename from tests/ui/issues/issue-27942.rs rename to tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs diff --git a/tests/ui/issues/issue-27942.stderr b/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr similarity index 100% rename from tests/ui/issues/issue-27942.stderr rename to tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr diff --git a/tests/ui/issues/issue-2761.rs b/tests/ui/macros/assert-with-custom-message.rs similarity index 100% rename from tests/ui/issues/issue-2761.rs rename to tests/ui/macros/assert-with-custom-message.rs diff --git a/tests/ui/issues/issue-27815.rs b/tests/ui/structs/non-struct-in-struct-position.rs similarity index 100% rename from tests/ui/issues/issue-27815.rs rename to tests/ui/structs/non-struct-in-struct-position.rs diff --git a/tests/ui/issues/issue-27815.stderr b/tests/ui/structs/non-struct-in-struct-position.stderr similarity index 100% rename from tests/ui/issues/issue-27815.stderr rename to tests/ui/structs/non-struct-in-struct-position.stderr diff --git a/tests/ui/issues/issue-27842.rs b/tests/ui/tuple/tuple-bracket-index-suggest-dot.rs similarity index 100% rename from tests/ui/issues/issue-27842.rs rename to tests/ui/tuple/tuple-bracket-index-suggest-dot.rs diff --git a/tests/ui/issues/issue-27842.stderr b/tests/ui/tuple/tuple-bracket-index-suggest-dot.stderr similarity index 100% rename from tests/ui/issues/issue-27842.stderr rename to tests/ui/tuple/tuple-bracket-index-suggest-dot.stderr From f6ac8642ff0b935254e2074225511af54a343f07 Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 27 Jun 2026 03:21:21 +0200 Subject: [PATCH 62/77] bless batch --- .../resolve-method-with-missing-assoc-type.rs | 3 +++ .../resolve-method-with-missing-assoc-type.stderr | 8 ++++---- tests/ui/binop/binop-subtyping-lifetimes.rs | 13 +++++++------ tests/ui/borrowck/enum-variants-share-field-name.rs | 5 +++-- .../derive-copy-clone-non-copy-field-diagnostic.rs | 4 ++++ ...rive-copy-clone-non-copy-field-diagnostic.stderr | 4 ++-- tests/ui/drop/dropflag-reinit-in-loop.rs | 8 ++++---- .../ui/higher-ranked/region-leak-rc-and-mut-ptr.rs | 4 ++++ .../trait-method-return-lifetime-mismatch.rs | 2 ++ .../trait-method-return-lifetime-mismatch.stderr | 12 ++++++------ tests/ui/macros/assert-with-custom-message.rs | 1 + tests/ui/structs/non-struct-in-struct-position.rs | 3 +++ .../ui/structs/non-struct-in-struct-position.stderr | 8 ++++---- tests/ui/tuple/tuple-bracket-index-suggest-dot.rs | 4 ++++ .../ui/tuple/tuple-bracket-index-suggest-dot.stderr | 6 +++--- 15 files changed, 54 insertions(+), 31 deletions(-) diff --git a/tests/ui/associated-types/resolve-method-with-missing-assoc-type.rs b/tests/ui/associated-types/resolve-method-with-missing-assoc-type.rs index 883a8397e5a9e..2c892fae7b930 100644 --- a/tests/ui/associated-types/resolve-method-with-missing-assoc-type.rs +++ b/tests/ui/associated-types/resolve-method-with-missing-assoc-type.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Test we don't ICE on item resolution when associated type is omitted. //@ edition:2015 + use std::ops::BitXor; fn main() { diff --git a/tests/ui/associated-types/resolve-method-with-missing-assoc-type.stderr b/tests/ui/associated-types/resolve-method-with-missing-assoc-type.stderr index 0dcb585033d07..b942ad8d26556 100644 --- a/tests/ui/associated-types/resolve-method-with-missing-assoc-type.stderr +++ b/tests/ui/associated-types/resolve-method-with-missing-assoc-type.stderr @@ -1,5 +1,5 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-28344.rs:5:17 + --> $DIR/resolve-method-with-missing-assoc-type.rs:8:17 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^ @@ -13,7 +13,7 @@ LL | let x: u8 = ::bitor(0 as u8, 0 as u8); | ++++ + error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified - --> $DIR/issue-28344.rs:5:17 + --> $DIR/resolve-method-with-missing-assoc-type.rs:8:17 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^ @@ -24,7 +24,7 @@ LL | let x: u8 = BitXor::::bitor(0 as u8, 0 as u8); | +++++++++++++++++++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-28344.rs:10:13 + --> $DIR/resolve-method-with-missing-assoc-type.rs:13:13 | LL | let g = BitXor::bitor; | ^^^^^^ @@ -37,7 +37,7 @@ LL | let g = ::bitor; | ++++ + error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified - --> $DIR/issue-28344.rs:10:13 + --> $DIR/resolve-method-with-missing-assoc-type.rs:13:13 | LL | let g = BitXor::bitor; | ^^^^^^ diff --git a/tests/ui/binop/binop-subtyping-lifetimes.rs b/tests/ui/binop/binop-subtyping-lifetimes.rs index e10c60085072f..6456768fed939 100644 --- a/tests/ui/binop/binop-subtyping-lifetimes.rs +++ b/tests/ui/binop/binop-subtyping-lifetimes.rs @@ -1,10 +1,11 @@ +//! Regression test for . +//! +//! At one time, the `==` operator (and other binary operators) did not +//! support subtyping during type checking, and would therefore require +//! LHS and RHS to be exactly identical--i.e. to have the same lifetimes. +//! +//! This was fixed in 1a7fb7dc78439a704f024609ce3dc0beb1386552. //@ run-pass -// -// At one time, the `==` operator (and other binary operators) did not -// support subtyping during type checking, and would therefore require -// LHS and RHS to be exactly identical--i.e. to have the same lifetimes. -// -// This was fixed in 1a7fb7dc78439a704f024609ce3dc0beb1386552. #[derive(Copy, Clone)] struct Input<'a> { diff --git a/tests/ui/borrowck/enum-variants-share-field-name.rs b/tests/ui/borrowck/enum-variants-share-field-name.rs index 8737f03db1a59..d357d805ea22a 100644 --- a/tests/ui/borrowck/enum-variants-share-field-name.rs +++ b/tests/ui/borrowck/enum-variants-share-field-name.rs @@ -1,8 +1,9 @@ +//! Regression test for . +//! Test that a field can have the same name in different variants +//! of an enum, and borrowck won't treat them as the same value. //@ check-pass #![allow(unused_assignments)] #![allow(unused_variables)] -// Test that a field can have the same name in different variants -// of an enum pub enum Foo { X { foo: u32 }, diff --git a/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs b/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs index 9966c24a7441e..6053b603cc8fa 100644 --- a/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs +++ b/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test anon fields in tuple-syntax structs which don't implement trait +//! get nice error message mentioning the type of field and its span. + struct Foo; #[derive(Copy, Clone)] struct Bar(Foo); diff --git a/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr b/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr index 3b4ad58b1f080..a997fc0aa0d98 100644 --- a/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr +++ b/tests/ui/derives/clone-copy/derive-copy-clone-non-copy-field-diagnostic.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-27340.rs:3:8 + --> $DIR/derive-copy-clone-non-copy-field-diagnostic.rs:7:8 | LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion @@ -7,7 +7,7 @@ LL | struct Bar(Foo); | ^^^ --- this field does not implement `Copy` error[E0277]: the trait bound `Foo: Clone` is not satisfied - --> $DIR/issue-27340.rs:3:12 + --> $DIR/derive-copy-clone-non-copy-field-diagnostic.rs:7:12 | LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion diff --git a/tests/ui/drop/dropflag-reinit-in-loop.rs b/tests/ui/drop/dropflag-reinit-in-loop.rs index b89497241e096..04fb8eaee965e 100644 --- a/tests/ui/drop/dropflag-reinit-in-loop.rs +++ b/tests/ui/drop/dropflag-reinit-in-loop.rs @@ -1,9 +1,9 @@ +//! Regression test for . +//! Check that when a `let`-binding occurs in a loop, its associated +//! drop-flag is reinitialized (to indicate "needs-drop" at the end of +//! the owning variable's scope). //@ run-pass -// Check that when a `let`-binding occurs in a loop, its associated -// drop-flag is reinitialized (to indicate "needs-drop" at the end of -// the owning variable's scope). - struct A<'a>(&'a mut i32); impl<'a> Drop for A<'a> { diff --git a/tests/ui/higher-ranked/region-leak-rc-and-mut-ptr.rs b/tests/ui/higher-ranked/region-leak-rc-and-mut-ptr.rs index 23814b284e905..754e3ce2167a7 100644 --- a/tests/ui/higher-ranked/region-leak-rc-and-mut-ptr.rs +++ b/tests/ui/higher-ranked/region-leak-rc-and-mut-ptr.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! Region variables escaped comparison for common supertype, which led +//! `Rc` and `*mut Fn(&T)` to break. //@ check-pass + #![allow(dead_code)] use std::rc::Rc; diff --git a/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs b/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs index 1c2e6456937bb..91a18bfbf4390 100644 --- a/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs +++ b/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test internal compiler structs do not leak into error message. //@ dont-require-annotations: NOTE pub trait Resources<'a> {} diff --git a/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr b/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr index 671875aa7e2ac..bab0f4c180958 100644 --- a/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr +++ b/tests/ui/lifetimes/lifetime-errors/trait-method-return-lifetime-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-27942.rs:7:25 + --> $DIR/trait-method-return-lifetime-mismatch.rs:9:25 | LL | fn select(&self) -> BufferViewHandle; | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ LL | fn select(&self) -> BufferViewHandle; = note: expected trait `Resources<'_>` found trait `Resources<'a>` note: the lifetime `'a` as defined here... - --> $DIR/issue-27942.rs:5:18 + --> $DIR/trait-method-return-lifetime-mismatch.rs:7:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { | ^^ note: ...does not necessarily outlive the anonymous lifetime defined here - --> $DIR/issue-27942.rs:7:15 + --> $DIR/trait-method-return-lifetime-mismatch.rs:9:15 | LL | fn select(&self) -> BufferViewHandle; | ^^^^^ error[E0308]: mismatched types - --> $DIR/issue-27942.rs:7:25 + --> $DIR/trait-method-return-lifetime-mismatch.rs:9:25 | LL | fn select(&self) -> BufferViewHandle; | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ LL | fn select(&self) -> BufferViewHandle; = note: expected trait `Resources<'_>` found trait `Resources<'a>` note: the anonymous lifetime defined here... - --> $DIR/issue-27942.rs:7:15 + --> $DIR/trait-method-return-lifetime-mismatch.rs:9:15 | LL | fn select(&self) -> BufferViewHandle; | ^^^^^ note: ...does not necessarily outlive the lifetime `'a` as defined here - --> $DIR/issue-27942.rs:5:18 + --> $DIR/trait-method-return-lifetime-mismatch.rs:7:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { | ^^ diff --git a/tests/ui/macros/assert-with-custom-message.rs b/tests/ui/macros/assert-with-custom-message.rs index 6df7a5118b820..78a4a2d61cb9b 100644 --- a/tests/ui/macros/assert-with-custom-message.rs +++ b/tests/ui/macros/assert-with-custom-message.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ run-fail //@ error-pattern:custom message //@ needs-subprocess diff --git a/tests/ui/structs/non-struct-in-struct-position.rs b/tests/ui/structs/non-struct-in-struct-position.rs index 9e53014f45522..782808b8e8520 100644 --- a/tests/ui/structs/non-struct-in-struct-position.rs +++ b/tests/ui/structs/non-struct-in-struct-position.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test usage of struct literal syntax with non-structs doesn't ICE. + mod A {} fn main() { diff --git a/tests/ui/structs/non-struct-in-struct-position.stderr b/tests/ui/structs/non-struct-in-struct-position.stderr index 43f78ccf6395a..667ebe7387d07 100644 --- a/tests/ui/structs/non-struct-in-struct-position.stderr +++ b/tests/ui/structs/non-struct-in-struct-position.stderr @@ -1,23 +1,23 @@ error[E0574]: expected struct, variant or union type, found module `A` - --> $DIR/issue-27815.rs:4:13 + --> $DIR/non-struct-in-struct-position.rs:7:13 | LL | let u = A { x: 1 }; | ^ not a struct, variant or union type error[E0574]: expected struct, variant or union type, found builtin type `u32` - --> $DIR/issue-27815.rs:5:13 + --> $DIR/non-struct-in-struct-position.rs:8:13 | LL | let v = u32 { x: 1 }; | ^^^ not a struct, variant or union type error[E0574]: expected struct, variant or union type, found module `A` - --> $DIR/issue-27815.rs:7:9 + --> $DIR/non-struct-in-struct-position.rs:10:9 | LL | A { x: 1 } => {} | ^ not a struct, variant or union type error[E0574]: expected struct, variant or union type, found builtin type `u32` - --> $DIR/issue-27815.rs:9:9 + --> $DIR/non-struct-in-struct-position.rs:12:9 | LL | u32 { x: 1 } => {} | ^^^ not a struct, variant or union type diff --git a/tests/ui/tuple/tuple-bracket-index-suggest-dot.rs b/tests/ui/tuple/tuple-bracket-index-suggest-dot.rs index 060d3b34e09d9..a72be060529c8 100644 --- a/tests/ui/tuple/tuple-bracket-index-suggest-dot.rs +++ b/tests/ui/tuple/tuple-bracket-index-suggest-dot.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test we suggest the use of dot syntax when user is trying to index +//! tuple via square brackets. + fn main() { let tup = (0, 1, 2); // the case where we show a suggestion diff --git a/tests/ui/tuple/tuple-bracket-index-suggest-dot.stderr b/tests/ui/tuple/tuple-bracket-index-suggest-dot.stderr index f388fdf85cde5..f6e6528572661 100644 --- a/tests/ui/tuple/tuple-bracket-index-suggest-dot.stderr +++ b/tests/ui/tuple/tuple-bracket-index-suggest-dot.stderr @@ -1,5 +1,5 @@ error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer})` - --> $DIR/issue-27842.rs:4:16 + --> $DIR/tuple-bracket-index-suggest-dot.rs:8:16 | LL | let _ = tup[0]; | ^^^ help: to access tuple element `0`, use: `.0` @@ -7,7 +7,7 @@ LL | let _ = tup[0]; = help: tuples are indexed with a dot and a literal index: `tuple.0`, `tuple.1`, etc. error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer})` - --> $DIR/issue-27842.rs:9:16 + --> $DIR/tuple-bracket-index-suggest-dot.rs:13:16 | LL | let _ = tup[i]; | ^^^ @@ -15,7 +15,7 @@ LL | let _ = tup[i]; = help: tuples are indexed with a dot and a literal index: `tuple.0`, `tuple.1`, etc. error[E0608]: cannot index into a value of type `({integer},)` - --> $DIR/issue-27842.rs:14:16 + --> $DIR/tuple-bracket-index-suggest-dot.rs:18:16 | LL | let _ = tup[3]; | ^^^ From d69c87aed2c5234c0d78569b448d1dc17fdee331 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski Date: Sat, 27 Jun 2026 01:36:56 -0400 Subject: [PATCH 63/77] Upgrade `jsonsocck` and `jsondoclint` to edition 2024. --- src/tools/jsondocck/Cargo.toml | 2 +- src/tools/jsondoclint/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index 80fc26cbe6680..f2ae68f7fbd69 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jsondocck" version = "0.1.0" -edition = "2021" +edition = "2024" [dependencies] jsonpath-rust = "1.0.0" diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index cc8ecefd530b4..848c0b37ae94e 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jsondoclint" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From f9a88c6b46c32fa7752a4349e0fca807d4cf5b48 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 27 Jun 2026 05:39:48 +0000 Subject: [PATCH 64/77] Prepare for merging from rust-lang/rust This updates the rust-version file to 16761606d606b6ec4d0c88fc9251670742ad9fd2. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 10d09bd1f1ebd..d7711535dbf29 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -40557f6225e337d68c8d4f086557ce54135f5dd9 +16761606d606b6ec4d0c88fc9251670742ad9fd2 From c3864bee809f41cca3d1eace7e7c7a93f0c1a091 Mon Sep 17 00:00:00 2001 From: Rain Date: Fri, 26 Jun 2026 20:12:27 -0700 Subject: [PATCH 65/77] rustdoc: show impl Trait> for Foreign, etc on Local's docs This is a generalization of PR 92940: that PR handled cases like `impl Foreign for Box`, but was missing handling for a few other closely related cases. My particular interest was with showing `impl From> for Box` in camino's documentation. But I ended up handling a bunch of related cases along the way. I'm new to rustdoc so please let me know if I got anything wrong :) took a bit to fully understand how this worked. --- src/librustdoc/formats/cache.rs | 45 ++++++++------ .../impl/impl-fundamental-nesting.rs | 58 +++++++++++++++++++ .../rustdoc-json/impls/fundamental_nesting.rs | 57 ++++++++++++++++++ 3 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 tests/rustdoc-html/impl/impl-fundamental-nesting.rs create mode 100644 tests/rustdoc-json/impls/fundamental_nesting.rs diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index fee783133133f..ccee062584e01 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -233,6 +233,30 @@ impl Cache { } } +impl CacheBuilder<'_, '_> { + /// Extends `dids` with ones that an impl should be associated with for a type appearing in its + /// `Self` type or trait generic arguments, accounting for references and `#[fundamental]` + /// wrappers. + /// + /// This ensures that impls like `impl Trait> for Foreign`, `impl Trait for + /// Box`, and other variations of these, are documented on `Local`'s page. + fn extend_with_fundamental_dids(&self, ty: &clean::Type, dids: &mut FxIndexSet) { + dids.extend(ty.def_id(self.cache)); + // without_borrowed_ref allows cases like `impl Trait<&Box> for Foreign` to be + // handled by this function. (This is rare in practice, but easy to handle here.) + if let clean::Type::Path { path } = ty.without_borrowed_ref() + && let Some(generics) = path.generics() + && let ty::Adt(adt, _) = + self.tcx.type_of(path.def_id()).instantiate_identity().skip_norm_wip().kind() + && adt.is_fundamental() + { + for inner in generics { + self.extend_with_fundamental_dids(inner, dids); + } + } + } +} + impl DocFolder for CacheBuilder<'_, '_> { fn fold_item(&mut self, item: clean::Item) -> Option { if item.item_id.is_local() { @@ -418,22 +442,9 @@ impl DocFolder for CacheBuilder<'_, '_> { // Note: matching twice to restrict the lifetime of the `i` borrow. let mut dids = FxIndexSet::default(); match i.for_ { - clean::Type::Path { ref path } - | clean::BorrowedRef { type_: clean::Type::Path { ref path }, .. } => { - dids.insert(path.def_id()); - if let Some(generics) = path.generics() - && let ty::Adt(adt, _) = self - .tcx - .type_of(path.def_id()) - .instantiate_identity() - .skip_norm_wip() - .kind() - && adt.is_fundamental() - { - for ty in generics { - dids.extend(ty.def_id(self.cache)); - } - } + clean::Type::Path { .. } + | clean::BorrowedRef { type_: clean::Type::Path { .. }, .. } => { + self.extend_with_fundamental_dids(&i.for_, &mut dids); } clean::DynTrait(ref bounds, _) | clean::BorrowedRef { type_: clean::DynTrait(ref bounds, _), .. } => { @@ -452,7 +463,7 @@ impl DocFolder for CacheBuilder<'_, '_> { && let Some(generics) = trait_.generics() { for bound in generics { - dids.extend(bound.def_id(self.cache)); + self.extend_with_fundamental_dids(bound, &mut dids); } } let impl_item = Impl { impl_item: item }; diff --git a/tests/rustdoc-html/impl/impl-fundamental-nesting.rs b/tests/rustdoc-html/impl/impl-fundamental-nesting.rs new file mode 100644 index 0000000000000..25aed33e53514 --- /dev/null +++ b/tests/rustdoc-html/impl/impl-fundamental-nesting.rs @@ -0,0 +1,58 @@ +// Followup to https://github.com/rust-lang/rust/issues/92940 and impl-box.rs. +// +// Show traits implemented on fundamental types that wrap local ones: nested edition. + +#![crate_name = "foo"] + +use std::pin::Pin; + +pub struct Local; + +//@ has 'foo/struct.Local.html' + +// Nested fundamental + foreign Self. +//@ has '-' '//*[@id="impl-From%3CBox%3CLocal%3E%3E-for-String"]' 'impl From> for String' +impl From> for String { + fn from(_: Box) -> String { + String::new() + } +} + +// Also test with Pin. +//@ has '-' '//*[@id="impl-From%3CPin%3CLocal%3E%3E-for-u8"]' 'impl From> for u8' +impl From> for u8 { + fn from(_: Pin) -> u8 { + 0 + } +} + +// Reference to a fundamental wrapper. +//@ has '-' '//*[@id="impl-From%3C%26Box%3CLocal%3E%3E-for-u16"]' "impl<'a> From<&'a Box> for u16" +impl<'a> From<&'a Box> for u16 { + fn from(_: &'a Box) -> u16 { + 0 + } +} + +// Nested two levels deep in Self. +//@ has '-' '//*[@id="impl-From%3Cu32%3E-for-Box%3CBox%3CLocal%3E%3E"]' 'impl From for Box>' +impl From for Box> { + fn from(_: u32) -> Box> { + Box::new(Box::new(Local)) + } +} + +// Mixed fundamental wrappers in Self. +//@ has '-' '//*[@id="impl-From%3Cu64%3E-for-Pin%3CBox%3CLocal%3E%3E"]' 'impl From for Pin>' +impl From for Pin> { + fn from(_: u64) -> Pin> { + Pin::new(Box::new(Local)) + } +} + +// A non-fundamental wrapper must not show up on Local's page, but it should still be listed on the +// trait's own page. +pub trait Marker {} +//@ has 'foo/trait.Marker.html' '//*[@id="impl-Marker-for-Vec%3CLocal%3E"]' 'impl Marker for Vec' +//@ !has 'foo/struct.Local.html' '//*[@id="impl-Marker-for-Vec%3CLocal%3E"]' 'impl Marker for Vec' +impl Marker for Vec {} diff --git a/tests/rustdoc-json/impls/fundamental_nesting.rs b/tests/rustdoc-json/impls/fundamental_nesting.rs new file mode 100644 index 0000000000000..a6aefb94f961f --- /dev/null +++ b/tests/rustdoc-json/impls/fundamental_nesting.rs @@ -0,0 +1,57 @@ +// Companion to tests/rustdoc-html/impl/impl-fundamental-nesting.rs. +// +// Show traits implemented on fundamental types that wrap local ones: nested edition. + +use std::pin::Pin; + +pub struct Local; + +// Nested fundamental + foreign Self. +/// from box local +impl From> for String { + fn from(_: Box) -> String { + String::new() + } +} +//@ set from_box_local = "$.index[?(@.docs=='from box local')].id" +//@ has "$.index[?(@.name=='Local')].inner.struct.impls[*]" $from_box_local + +// Reference to a fundamental wrapper. +/// from ref box local +impl<'a> From<&'a Box> for u16 { + fn from(_: &'a Box) -> u16 { + 0 + } +} +//@ set from_ref_box_local = "$.index[?(@.docs=='from ref box local')].id" +//@ has "$.index[?(@.name=='Local')].inner.struct.impls[*]" $from_ref_box_local + +// Nested two levels deep in Self. +/// u32 for box box local +impl From for Box> { + fn from(_: u32) -> Box> { + Box::new(Box::new(Local)) + } +} +//@ set u32_for_box_box_local = "$.index[?(@.docs=='u32 for box box local')].id" +//@ has "$.index[?(@.name=='Local')].inner.struct.impls[*]" $u32_for_box_box_local + +// Mixed fundamental wrappers in Self. +/// u64 for pin box local +impl From for Pin> { + fn from(_: u64) -> Pin> { + Pin::new(Box::new(Local)) + } +} +//@ set u64_for_pin_box_local = "$.index[?(@.docs=='u64 for pin box local')].id" +//@ has "$.index[?(@.name=='Local')].inner.struct.impls[*]" $u64_for_pin_box_local + +// A non-fundamental wrapper must not associate the impl with Local, but the impl must still be +// listed on the trait itself. +pub trait Marker {} + +/// marker for vec local +impl Marker for Vec {} +//@ set marker_for_vec_local = "$.index[?(@.docs=='marker for vec local')].id" +//@ !has "$.index[?(@.name=='Local')].inner.struct.impls[*]" $marker_for_vec_local +//@ has "$.index[?(@.name=='Marker')].inner.trait.implementations[*]" $marker_for_vec_local From 5eb878a65c0311c03285b573812e0fa660bd26e0 Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 27 Jun 2026 14:00:46 +0200 Subject: [PATCH 66/77] move batch --- .../nested-fnonce-output-projection.rs} | 0 .../projection-as-type-alias.rs} | 0 .../issue-28600.rs => extern/extern-c-method-with-str-param.rs} | 0 .../issue-28936.rs => inference/closure-arg-lifetime-by-ref.rs} | 0 .../field-borrow-lifetime-inference.rs} | 0 .../rfc-1238-nonparametric-dropck/must-work-ex1.rs} | 0 .../rfc-1238-nonparametric-dropck/must-work-ex2.rs} | 0 .../rfc-1238-nonparametric-dropck/reject-ex1.rs} | 0 .../rfc-1238-nonparametric-dropck/reject-ex1.stderr} | 0 .../rfc-1238-nonparametric-dropck/ugeh-ex1.rs} | 0 tests/ui/{issues/issue-28472.rs => span/foreign-item-vis-span.rs} | 0 .../issue-28472.stderr => span/foreign-item-vis-span.stderr} | 0 .../issue-28776.rs => unsafe/unsafe-fn-called-through-ref.rs} | 0 .../unsafe-fn-called-through-ref.stderr} | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-28550.rs => associated-types/nested-fnonce-output-projection.rs} (100%) rename tests/ui/{issues/issue-28828.rs => associated-types/projection-as-type-alias.rs} (100%) rename tests/ui/{issues/issue-28600.rs => extern/extern-c-method-with-str-param.rs} (100%) rename tests/ui/{issues/issue-28936.rs => inference/closure-arg-lifetime-by-ref.rs} (100%) rename tests/ui/{issues/issue-28999.rs => lifetimes/field-borrow-lifetime-inference.rs} (100%) rename tests/ui/{issues/issue-28498-must-work-ex1.rs => rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs} (100%) rename tests/ui/{issues/issue-28498-must-work-ex2.rs => rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs} (100%) rename tests/ui/{span/issue28498-reject-ex1.rs => rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs} (100%) rename tests/ui/{span/issue28498-reject-ex1.stderr => rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr} (100%) rename tests/ui/{issues/issue-28498-ugeh-ex1.rs => rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs} (100%) rename tests/ui/{issues/issue-28472.rs => span/foreign-item-vis-span.rs} (100%) rename tests/ui/{issues/issue-28472.stderr => span/foreign-item-vis-span.stderr} (100%) rename tests/ui/{issues/issue-28776.rs => unsafe/unsafe-fn-called-through-ref.rs} (100%) rename tests/ui/{issues/issue-28776.stderr => unsafe/unsafe-fn-called-through-ref.stderr} (100%) diff --git a/tests/ui/issues/issue-28550.rs b/tests/ui/associated-types/nested-fnonce-output-projection.rs similarity index 100% rename from tests/ui/issues/issue-28550.rs rename to tests/ui/associated-types/nested-fnonce-output-projection.rs diff --git a/tests/ui/issues/issue-28828.rs b/tests/ui/associated-types/projection-as-type-alias.rs similarity index 100% rename from tests/ui/issues/issue-28828.rs rename to tests/ui/associated-types/projection-as-type-alias.rs diff --git a/tests/ui/issues/issue-28600.rs b/tests/ui/extern/extern-c-method-with-str-param.rs similarity index 100% rename from tests/ui/issues/issue-28600.rs rename to tests/ui/extern/extern-c-method-with-str-param.rs diff --git a/tests/ui/issues/issue-28936.rs b/tests/ui/inference/closure-arg-lifetime-by-ref.rs similarity index 100% rename from tests/ui/issues/issue-28936.rs rename to tests/ui/inference/closure-arg-lifetime-by-ref.rs diff --git a/tests/ui/issues/issue-28999.rs b/tests/ui/lifetimes/field-borrow-lifetime-inference.rs similarity index 100% rename from tests/ui/issues/issue-28999.rs rename to tests/ui/lifetimes/field-borrow-lifetime-inference.rs diff --git a/tests/ui/issues/issue-28498-must-work-ex1.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs similarity index 100% rename from tests/ui/issues/issue-28498-must-work-ex1.rs rename to tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs diff --git a/tests/ui/issues/issue-28498-must-work-ex2.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs similarity index 100% rename from tests/ui/issues/issue-28498-must-work-ex2.rs rename to tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs diff --git a/tests/ui/span/issue28498-reject-ex1.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs similarity index 100% rename from tests/ui/span/issue28498-reject-ex1.rs rename to tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs diff --git a/tests/ui/span/issue28498-reject-ex1.stderr b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr similarity index 100% rename from tests/ui/span/issue28498-reject-ex1.stderr rename to tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr diff --git a/tests/ui/issues/issue-28498-ugeh-ex1.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs similarity index 100% rename from tests/ui/issues/issue-28498-ugeh-ex1.rs rename to tests/ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs diff --git a/tests/ui/issues/issue-28472.rs b/tests/ui/span/foreign-item-vis-span.rs similarity index 100% rename from tests/ui/issues/issue-28472.rs rename to tests/ui/span/foreign-item-vis-span.rs diff --git a/tests/ui/issues/issue-28472.stderr b/tests/ui/span/foreign-item-vis-span.stderr similarity index 100% rename from tests/ui/issues/issue-28472.stderr rename to tests/ui/span/foreign-item-vis-span.stderr diff --git a/tests/ui/issues/issue-28776.rs b/tests/ui/unsafe/unsafe-fn-called-through-ref.rs similarity index 100% rename from tests/ui/issues/issue-28776.rs rename to tests/ui/unsafe/unsafe-fn-called-through-ref.rs diff --git a/tests/ui/issues/issue-28776.stderr b/tests/ui/unsafe/unsafe-fn-called-through-ref.stderr similarity index 100% rename from tests/ui/issues/issue-28776.stderr rename to tests/ui/unsafe/unsafe-fn-called-through-ref.stderr From 2e088054ddacaf5dad97624af7ca9c9f0764b326 Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Sun, 14 Jun 2026 01:11:36 +0200 Subject: [PATCH 67/77] fix: keep readable readiness when socket read end is closed Removing the readable readiness after a short read even when the read end is closed would mean that applications which strictly rely on the readable readiness (e.g. tokio) would no longer read zero (indicating EOF) on the closed socket. This is problematic as those applications could block indefinitely waiting for a readable event on the socket. --- src/tools/miri/src/shims/unix/socket.rs | 36 +++- .../libc/libc-socket-no-blocking-epoll.rs | 197 +++++++++++++++++- 2 files changed, 214 insertions(+), 19 deletions(-) diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs index ae882f8ff3a40..72b614f58d0a4 100644 --- a/src/tools/miri/src/shims/unix/socket.rs +++ b/src/tools/miri/src/shims/unix/socket.rs @@ -1487,9 +1487,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Only shutting down the write end doesn't cause an EPOLLHUP event // and thus we won't set the `write_closed` readiness for it here. readiness.write_closed |= is_read_write_shutdown; - // The Linux kernel also sets EPOLLIN when both ends of a socket are closed: + // The Linux kernel also sets EPOLLIN when the read end of a socket is closed: // - readiness.readable |= is_read_write_shutdown; + readiness.readable |= is_read_shutdown || is_read_write_shutdown; drop(readiness); @@ -1697,12 +1697,16 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Result> { let this = self.eval_context_mut(); - let SocketState::Connected(stream) = &mut *socket.state.borrow_mut() else { + let mut state = socket.state.borrow_mut(); + let SocketState::Connected(stream) = &mut *state else { panic!("try_non_block_send must only be called when the socket is connected") }; // This is a *non-blocking* write. let result = this.write_to_host(stream, length, buffer_ptr)?; + + drop(state); + match result { Err(IoError::HostError(e)) if matches!(e.kind(), io::ErrorKind::NotConnected | io::ErrorKind::WouldBlock) => @@ -1715,8 +1719,13 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // would be returned on UNIX-like systems. We thus remap this error to an EWOULDBLOCK. interp_ok(Err(IoError::HostError(io::ErrorKind::WouldBlock.into()))) } - Ok(bytes_written) if bytes_written < length => { - // We had a short write. On Unix hosts using the `epoll` and `kqueue` backends, a + Ok(bytes_written) + if bytes_written < length && !socket.io_readiness.borrow().write_closed => + { + // We had a short write. (Note that we don't want to clear the writable readiness for + // sockets whose write end has already been closed as those never block a write, i.e., + // they are always write-ready.) + // On Unix hosts using the `epoll` and `kqueue` backends, a // short write means that the write buffer is full. We update the readiness // accordingly, which means that next time we see "writable" we will report an epoll // edge. Some applications (e.g. tokio) rely on this behavior; see @@ -1820,7 +1829,8 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Result> { let this = self.eval_context_mut(); - let SocketState::Connected(stream) = &mut *socket.state.borrow_mut() else { + let mut state = socket.state.borrow_mut(); + let SocketState::Connected(stream) = &mut *state else { panic!("try_non_block_recv must only be called when the socket is connected") }; @@ -1832,6 +1842,9 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { length, buffer_ptr, )?; + + drop(state); + match result { Err(IoError::HostError(e)) if matches!(e.kind(), io::ErrorKind::NotConnected | io::ErrorKind::WouldBlock) => @@ -1844,9 +1857,16 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // would be returned on UNIX-like systems. We thus remap this error to an EWOULDBLOCK. interp_ok(Err(IoError::HostError(io::ErrorKind::WouldBlock.into()))) } - Ok(bytes_read) if !should_peek && bytes_read < length && bytes_read > 0 => { + Ok(bytes_read) + if !should_peek + && bytes_read < length + && bytes_read > 0 + && !socket.io_readiness.borrow().read_closed => + { // We had a short read (and were not peeking). (Note that reading 0 bytes is guaranteed - // to indicate EOF, and can never happen spuriously, so we have to exclude that case.) + // to indicate EOF, and can never happen spuriously, so we have to exclude that case. + // We also don't want to clear the readable readiness for sockets whose read end has + // already been closed as those never block a read, i.e., they are always read-ready.) // On Unix hosts using the `epoll` and `kqueue` backends, a short read means that the // read buffer is empty. We update the readiness accordingly, which means that next time // we see "readable" we will report an epoll edge. Some applications (e.g. tokio) rely on diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs index 9ed0b9c735979..fd657db582acb 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs @@ -1,5 +1,8 @@ //@only-target: linux android illumos //@compile-flags: -Zmiri-disable-isolation +//@revisions: windows_host unix_host +//@[unix_host] ignore-host: windows +//@[windows_host] only-host: windows //@run-native #![feature(io_error_inprogress)] @@ -28,6 +31,8 @@ fn main() { test_readiness_after_short_read(); test_readiness_after_short_peek(); test_readiness_after_short_write(); + test_readable_after_read_shutdown_and_short_read(); + test_writable_after_write_shutdown_with_full_buffer(); } /// Test that connecting to a server socket works when the client @@ -562,24 +567,14 @@ fn test_readiness_after_short_write() { unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); - // Spawn the server thread. - let server_thread = thread::spawn(move || { - let (peerfd, _) = net::accept_ipv4(server_sockfd).unwrap(); - // Return the peer socket file descriptor such that we can use - // it after joining the server thread. - peerfd - }); - net::connect_ipv4(client_sockfd, addr).unwrap(); + let (peerfd, _) = net::accept_ipv4(server_sockfd).unwrap(); unsafe { // Change client socket to be non-blocking. errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)); } - // The peer socket is a blocking socket. - let peerfd = server_thread.join().unwrap(); - // Add client socket with writable interest to epoll. epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLOUT).unwrap(); @@ -636,3 +631,183 @@ fn test_readiness_after_short_write() { // We should again be able to write into the socket. libc_utils::write_all(client_sockfd, &buffer).unwrap(); } + +/// Test that Miri correctly keeps the readable readiness when the read end of the client +/// socket has been closed -- even after a short read. +fn test_readable_after_read_shutdown_and_short_read() { + let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); + + // Spawn the server thread. + let server_thread = thread::spawn(move || { + let (peerfd, _) = net::accept_ipv4(server_sockfd).unwrap(); + + // Write `TEST_BYTES` into the stream. + libc_utils::write_all(peerfd, TEST_BYTES).unwrap(); + }); + + net::connect_ipv4(client_sockfd, addr).unwrap(); + + unsafe { + // Change client socket to be non-blocking. + errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)); + } + + server_thread.join().unwrap(); + + // Close the read end of the client socket. + unsafe { + errno_check(libc::shutdown(client_sockfd, libc::SHUT_RD)); + } + + // Add client socket with "read closed" and "readable" interest to epoll. + epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLIN | EPOLLRDHUP).unwrap(); + + let events = if cfg!(windows_host) { + // On Windows hosts, the TCP connection is reset when the read-end of the + // socket is closed whilst there still being some unread/incoming data. + // We thus also expect the EPOLLHUP readiness (we don't need to register it, + // as `epoll_wait` registers it implicitly). + // See : + // "For TCP sockets, if there is still data queued on the socket waiting to + // be received, or data arrives subsequently, the connection is reset, since + // the data cannot be delivered to the user" + EPOLLIN | EPOLLRDHUP | EPOLLHUP + } else { + EPOLLIN | EPOLLRDHUP + }; + + // Ensure that the socket is readable and that its read end is closed. + check_epoll_wait(epfd, &[Ev { events, data: client_sockfd }], -1); + + let mut buffer = [0u8; 1024]; + + if cfg!(windows_host) { + // Because the TCP connection has been reset on Windows hosts, + // we cannot read anything from the client socket anymore. + // We thus only test that the connection has indeed been reset + // and then we return from the test. + let err = unsafe { + errno_result(libc::read( + client_sockfd, + buffer.as_mut_ptr().cast(), + // Attempt to read a chunk of 16 bytes. + 16, + )) + .unwrap_err() + }; + assert_eq!(err.kind(), ErrorKind::ConnectionAborted); + return; + } + + // We're not on a Windows host. + + // We want to read in chunks of 16 bytes. To ensure we get a short read, `TEST_BYTES.len()` + // must not be dividable by 16. + assert!(TEST_BYTES.len() % 16 != 0); + + let mut total_bytes_read = 0; + // Read everything from the socket until we get a short read. + // We don't want to provide `TEST_BYTES.len()` as `count` because then we won't trigger + // a short read. + loop { + let bytes_read = unsafe { + errno_result(libc::read( + client_sockfd, + buffer.as_mut_ptr().byte_add(total_bytes_read).cast(), + // Read a chunk of 16 bytes. + 16, + )) + .unwrap() + }; + + total_bytes_read += bytes_read as usize; + if bytes_read < 16 { + // We had a short read; we thus assume the read buffer is empty. + break; + } + } + assert_eq!(total_bytes_read, TEST_BYTES.len()); + + // We had a short read because `buffer` is bigger than `TEST_BYTES`. + // Because the read end of the socket is closed, we should still be able to + // read to detect EOFs. + + // Ensure that the "readable" and "read closed" readiness flags are still set. + assert_eq!( + current_epoll_readiness::<8>(client_sockfd, EPOLLIN | EPOLLET | EPOLLRDHUP), + EPOLLIN | EPOLLRDHUP + ); + + let mut buffer = [1u8; 16]; + let bytes_read = unsafe { + errno_result(libc::read(client_sockfd, buffer.as_mut_ptr().cast(), buffer.len())).unwrap() + }; + // The read should not block and return 0, indicating EOF. + assert_eq!(bytes_read, 0); +} + +/// Test that the writable readiness gets set when the write end of a socket +/// is closed -- even when the socket write buffer is full. +fn test_writable_after_write_shutdown_with_full_buffer() { + let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); + + net::connect_ipv4(client_sockfd, addr).unwrap(); + net::accept_ipv4(server_sockfd).unwrap(); + + unsafe { + // Change client socket to be non-blocking. + errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)); + } + + // Add client socket with level-triggered "writable" and "write closed" interest to epoll. + epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLHUP).unwrap(); + + // Wait until the socket becomes writable. + check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); + + // We now want to fill the write buffer of the socket by repeatedly writing + // `buffer` into it. The last write should then be a short write. + // We assume/hope that the write buffer length is not divisible by 1039. + let buffer = [123u8; 1039]; + + loop { + let result = unsafe { + errno_result(libc::write(client_sockfd, buffer.as_ptr().cast(), buffer.len())) + }; + + match result { + Ok(bytes_written) => { + if (bytes_written as usize) < buffer.len() { + // We had a short write; we thus assume the write buffer is full. + break; + } + } + Err(err) if err.kind() == ErrorKind::WouldBlock => { + // Windows and Apple hosts behave weirdly when attempting to fill up the write buffer. + // Instead of doing a short write to completely fill the buffer, they can return an + // EWOULDBLOCK when the next write wouldn't fit into the buffer. + // When we get such an error, we also assume the write buffer is full. + break; + } + Err(err) => panic!("unexpected error whilst filling up buffer: {err}"), + } + } + + // The write buffer is full; because this is a level-triggered interest, + // a readiness of 0 means that the socket would now block on writes. + check_epoll_wait(epfd, &[], 0); + + // Close the socket write end. + unsafe { + errno_check(libc::shutdown(client_sockfd, libc::SHUT_WR)); + } + + // The socket should no longer block on writes after its write end is closed. + check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); +} From 80f8d1c182cf93e04f3a1610920124eb376f0714 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jun 2026 13:27:30 +0200 Subject: [PATCH 68/77] avoid Windows quirk, and make write test consistent with read test --- .../libc/libc-socket-no-blocking-epoll.rs | 63 +++++-------------- 1 file changed, 15 insertions(+), 48 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs index fd657db582acb..68c69cd5668e6 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs @@ -1,8 +1,5 @@ //@only-target: linux android illumos //@compile-flags: -Zmiri-disable-isolation -//@revisions: windows_host unix_host -//@[unix_host] ignore-host: windows -//@[windows_host] only-host: windows //@run-native #![feature(io_error_inprogress)] @@ -646,64 +643,29 @@ fn test_readable_after_read_shutdown_and_short_read() { // Write `TEST_BYTES` into the stream. libc_utils::write_all(peerfd, TEST_BYTES).unwrap(); + + // Close the write end, so that the reader will get an EOF. + // (We could alternatively test this by closing the read end of the client socket, + // but Windows has some special behavior when closing a read end while there's still + // data coming in, so we avoid that.) + unsafe { errno_check(libc::shutdown(peerfd, libc::SHUT_WR)) }; }); net::connect_ipv4(client_sockfd, addr).unwrap(); - unsafe { - // Change client socket to be non-blocking. - errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)); - } + // Change client socket to be non-blocking. + unsafe { errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)) }; server_thread.join().unwrap(); - // Close the read end of the client socket. - unsafe { - errno_check(libc::shutdown(client_sockfd, libc::SHUT_RD)); - } - // Add client socket with "read closed" and "readable" interest to epoll. epoll_ctl_add(epfd, client_sockfd, EPOLLET | EPOLLIN | EPOLLRDHUP).unwrap(); - let events = if cfg!(windows_host) { - // On Windows hosts, the TCP connection is reset when the read-end of the - // socket is closed whilst there still being some unread/incoming data. - // We thus also expect the EPOLLHUP readiness (we don't need to register it, - // as `epoll_wait` registers it implicitly). - // See : - // "For TCP sockets, if there is still data queued on the socket waiting to - // be received, or data arrives subsequently, the connection is reset, since - // the data cannot be delivered to the user" - EPOLLIN | EPOLLRDHUP | EPOLLHUP - } else { - EPOLLIN | EPOLLRDHUP - }; - // Ensure that the socket is readable and that its read end is closed. - check_epoll_wait(epfd, &[Ev { events, data: client_sockfd }], -1); + check_epoll_wait(epfd, &[Ev { events: EPOLLIN | EPOLLRDHUP, data: client_sockfd }], -1); let mut buffer = [0u8; 1024]; - if cfg!(windows_host) { - // Because the TCP connection has been reset on Windows hosts, - // we cannot read anything from the client socket anymore. - // We thus only test that the connection has indeed been reset - // and then we return from the test. - let err = unsafe { - errno_result(libc::read( - client_sockfd, - buffer.as_mut_ptr().cast(), - // Attempt to read a chunk of 16 bytes. - 16, - )) - .unwrap_err() - }; - assert_eq!(err.kind(), ErrorKind::ConnectionAborted); - return; - } - - // We're not on a Windows host. - // We want to read in chunks of 16 bytes. To ensure we get a short read, `TEST_BYTES.len()` // must not be dividable by 16. assert!(TEST_BYTES.len() % 16 != 0); @@ -741,11 +703,11 @@ fn test_readable_after_read_shutdown_and_short_read() { EPOLLIN | EPOLLRDHUP ); + // A read should not block and return 0, indicating EOF. let mut buffer = [1u8; 16]; let bytes_read = unsafe { errno_result(libc::read(client_sockfd, buffer.as_mut_ptr().cast(), buffer.len())).unwrap() }; - // The read should not block and return 0, indicating EOF. assert_eq!(bytes_read, 0); } @@ -810,4 +772,9 @@ fn test_writable_after_write_shutdown_with_full_buffer() { // The socket should no longer block on writes after its write end is closed. check_epoll_wait(epfd, &[Ev { events: EPOLLOUT, data: client_sockfd }], -1); + + // A write should not block and return an error. + let result = + unsafe { errno_result(libc::write(client_sockfd, buffer.as_ptr().cast(), buffer.len())) }; + assert_eq!(result.unwrap_err().kind(), ErrorKind::BrokenPipe); } From eb9bdc40dc474cdfdf9ee3fbfe06c6ccecad2940 Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 27 Jun 2026 14:08:25 +0200 Subject: [PATCH 69/77] bless batch --- src/tools/tidy/src/issues.txt | 1 - .../nested-fnonce-output-projection.rs | 2 ++ tests/ui/associated-types/projection-as-type-alias.rs | 3 +++ tests/ui/extern/extern-c-method-with-str-param.rs | 3 ++- tests/ui/inference/closure-arg-lifetime-by-ref.rs | 2 ++ tests/ui/lifetimes/field-borrow-lifetime-inference.rs | 3 +++ .../rfc-1238-nonparametric-dropck/must-work-ex1.rs | 7 +++---- .../rfc-1238-nonparametric-dropck/must-work-ex2.rs | 7 +++---- .../rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs | 10 ++++------ .../rfc-1238-nonparametric-dropck/reject-ex1.stderr | 2 +- .../ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs | 8 +++----- tests/ui/span/foreign-item-vis-span.rs | 3 ++- tests/ui/span/foreign-item-vis-span.stderr | 4 ++-- tests/ui/unsafe/unsafe-fn-called-through-ref.rs | 3 +++ tests/ui/unsafe/unsafe-fn-called-through-ref.stderr | 2 +- 15 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index b63f4d46139c7..db6008da59b34 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2442,7 +2442,6 @@ ui/span/issue-42234-unknown-receiver-type.rs ui/span/issue-43927-non-ADT-derive.rs ui/span/issue-71363.rs ui/span/issue-81800.rs -ui/span/issue28498-reject-ex1.rs ui/span/issue28498-reject-lifetime-param.rs ui/span/issue28498-reject-passed-to-fn.rs ui/span/issue28498-reject-trait-bound.rs diff --git a/tests/ui/associated-types/nested-fnonce-output-projection.rs b/tests/ui/associated-types/nested-fnonce-output-projection.rs index 31c7057d06f8c..aa03ca10430ac 100644 --- a/tests/ui/associated-types/nested-fnonce-output-projection.rs +++ b/tests/ui/associated-types/nested-fnonce-output-projection.rs @@ -1,4 +1,6 @@ +//! Regression test for . //@ run-pass + struct AT,T>(F::Output); struct BT,T>(A); diff --git a/tests/ui/associated-types/projection-as-type-alias.rs b/tests/ui/associated-types/projection-as-type-alias.rs index b5d7385cf28f0..b3e01be818e1f 100644 --- a/tests/ui/associated-types/projection-as-type-alias.rs +++ b/tests/ui/associated-types/projection-as-type-alias.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This failed to compile as associated types aliases were not normalized. //@ run-pass + pub trait Foo { type Out; } diff --git a/tests/ui/extern/extern-c-method-with-str-param.rs b/tests/ui/extern/extern-c-method-with-str-param.rs index a5427b94a57c5..d0fe55bd1d0f1 100644 --- a/tests/ui/extern/extern-c-method-with-str-param.rs +++ b/tests/ui/extern/extern-c-method-with-str-param.rs @@ -1,5 +1,6 @@ +//! Regression test for . +//! pub extern fn with parameter type &str inside struct impl caused ICE. //@ build-pass -// #28600 ICE: pub extern fn with parameter type &str inside struct impl struct Test; diff --git a/tests/ui/inference/closure-arg-lifetime-by-ref.rs b/tests/ui/inference/closure-arg-lifetime-by-ref.rs index 96503f0711d27..f00a38ea061c8 100644 --- a/tests/ui/inference/closure-arg-lifetime-by-ref.rs +++ b/tests/ui/inference/closure-arg-lifetime-by-ref.rs @@ -1,4 +1,6 @@ +//! Regression test for . //@ check-pass + pub type Session = i32; pub struct StreamParser<'a, T> { _tokens: T, diff --git a/tests/ui/lifetimes/field-borrow-lifetime-inference.rs b/tests/ui/lifetimes/field-borrow-lifetime-inference.rs index 572a0beff61f6..a8582dbd29b62 100644 --- a/tests/ui/lifetimes/field-borrow-lifetime-inference.rs +++ b/tests/ui/lifetimes/field-borrow-lifetime-inference.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! `this.v` was not constrained and inferred `'a`. //@ check-pass + pub struct Xyz<'a, V> { pub v: (V, &'a u32), } diff --git a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs index 813cd8645f923..9afd7ddbd88a9 100644 --- a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs +++ b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex1.rs @@ -1,8 +1,7 @@ +//! Test for . +//! Example taken from RFC 1238 text +//! . //@ run-pass -// Example taken from RFC 1238 text - -// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md -// #examples-of-code-that-must-continue-to-work use std::cell::Cell; diff --git a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs index 98514b1163675..4e8d403672641 100644 --- a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs +++ b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs @@ -1,8 +1,7 @@ +//! Test for . +//! Example taken from RFC 1238 text +//! . //@ run-pass -// Example taken from RFC 1238 text - -// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md -// #examples-of-code-that-must-continue-to-work use std::cell::Cell; diff --git a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs index 4d1b4125503b6..3209a17041f67 100644 --- a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs +++ b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.rs @@ -1,9 +1,7 @@ -// Example taken from RFC 1238 text - -// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md -// #examples-of-code-that-will-start-to-be-rejected - -// Compare against test/run-pass/issue28498-must-work-ex2.rs +//! Test for . +//! Example taken from RFC 1238 text +//! . +//! Compare against tests/ui/rfcs/rfc-1238-nonparametric-dropck/must-work-ex2.rs. use std::cell::Cell; diff --git a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr index 7b8af23a6cd7b..6e20f06d7fe4c 100644 --- a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr +++ b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/reject-ex1.stderr @@ -1,5 +1,5 @@ error[E0713]: borrow may still be in use when destructor runs - --> $DIR/issue28498-reject-ex1.rs:34:29 + --> $DIR/reject-ex1.rs:32:29 | LL | foo.data[0].1.set(Some(&foo.data[1])); | ^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs index f606d2489484a..722523c094329 100644 --- a/tests/ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs +++ b/tests/ui/rfcs/rfc-1238-nonparametric-dropck/ugeh-ex1.rs @@ -1,10 +1,8 @@ +//! Test for . +//! Example taken from RFC 1238 text +//! . //@ run-pass -// Example taken from RFC 1238 text - -// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md -// #example-of-the-unguarded-escape-hatch - #![feature(dropck_eyepatch)] use std::cell::Cell; diff --git a/tests/ui/span/foreign-item-vis-span.rs b/tests/ui/span/foreign-item-vis-span.rs index 6db1f9a5bddf9..839e07ea1b961 100644 --- a/tests/ui/span/foreign-item-vis-span.rs +++ b/tests/ui/span/foreign-item-vis-span.rs @@ -1,4 +1,5 @@ -// Check that the visibility modifier is included in the span of foreign items. +//! Regression test for . +//! Check that the visibility modifier is included in the span of foreign items. extern "C" { fn foo(); diff --git a/tests/ui/span/foreign-item-vis-span.stderr b/tests/ui/span/foreign-item-vis-span.stderr index 051ed25b6c9d9..912a338e4616a 100644 --- a/tests/ui/span/foreign-item-vis-span.stderr +++ b/tests/ui/span/foreign-item-vis-span.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `foo` is defined multiple times - --> $DIR/issue-28472.rs:6:3 + --> $DIR/foreign-item-vis-span.rs:7:3 | LL | fn foo(); | --------- previous definition of the value `foo` here @@ -11,7 +11,7 @@ LL | | fn foo(); = note: `foo` must be defined only once in the value namespace of this module error[E0428]: the name `foo` is defined multiple times - --> $DIR/issue-28472.rs:9:3 + --> $DIR/foreign-item-vis-span.rs:10:3 | LL | fn foo(); | --------- previous definition of the value `foo` here diff --git a/tests/ui/unsafe/unsafe-fn-called-through-ref.rs b/tests/ui/unsafe/unsafe-fn-called-through-ref.rs index e564ebcd110cb..d5ac06fe32956 100644 --- a/tests/ui/unsafe/unsafe-fn-called-through-ref.rs +++ b/tests/ui/unsafe/unsafe-fn-called-through-ref.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Unsafe fn could be called outside of unsafe block through autoderef. + use std::ptr; fn main() { diff --git a/tests/ui/unsafe/unsafe-fn-called-through-ref.stderr b/tests/ui/unsafe/unsafe-fn-called-through-ref.stderr index 3db94ee181017..6978839ed1c8b 100644 --- a/tests/ui/unsafe/unsafe-fn-called-through-ref.stderr +++ b/tests/ui/unsafe/unsafe-fn-called-through-ref.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `std::ptr::write` is unsafe and requires unsafe function or block - --> $DIR/issue-28776.rs:4:5 + --> $DIR/unsafe-fn-called-through-ref.rs:7:5 | LL | (&ptr::write)(1 as *mut _, 42); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function From 9ab513578e4301ed0837dcee582a914fca8496d6 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski Date: Sat, 27 Jun 2026 10:07:44 -0400 Subject: [PATCH 70/77] Upgrade `rustdoc-json-types` to 2024 edition. --- src/rustdoc-json-types/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml index 9e18691a9605a..ba6dc2d69e1ff 100644 --- a/src/rustdoc-json-types/Cargo.toml +++ b/src/rustdoc-json-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustdoc-json-types" version = "0.1.0" -edition = "2021" +edition = "2024" [lib] path = "lib.rs" From aac07469e653d3840c1a5ca2fb8e6c61cf33cc8c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jun 2026 15:33:09 +0200 Subject: [PATCH 71/77] run x86 intrinsic tests natively --- .../tests/pass/shims/x86/intrinsics-sha.rs | 1 + .../pass/shims/x86/intrinsics-x86-adx.rs | 1 + .../pass/shims/x86/intrinsics-x86-aes-vaes.rs | 10 +++++++-- .../pass/shims/x86/intrinsics-x86-avx.rs | 1 + .../pass/shims/x86/intrinsics-x86-avx2.rs | 1 + .../pass/shims/x86/intrinsics-x86-avx512.rs | 8 +++++++ .../pass/shims/x86/intrinsics-x86-bmi.rs | 1 + .../pass/shims/x86/intrinsics-x86-gfni.rs | 22 ++++++++++++++----- .../shims/x86/intrinsics-x86-pclmulqdq.rs | 1 + .../pass/shims/x86/intrinsics-x86-sse.rs | 1 + .../pass/shims/x86/intrinsics-x86-sse2.rs | 1 + .../shims/x86/intrinsics-x86-sse3-ssse3.rs | 1 + .../pass/shims/x86/intrinsics-x86-sse41.rs | 1 + .../pass/shims/x86/intrinsics-x86-sse42.rs | 1 + .../shims/x86/intrinsics-x86-vpclmulqdq.rs | 1 + .../tests/pass/shims/x86/intrinsics-x86.rs | 5 +++-- 16 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs index ae5731bc8a6a3..1e36867c4a0b6 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+sha,+sse2,+ssse3,+sse4.1 +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-adx.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-adx.rs index baa984e68d83b..87b2f5d3d80b3 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-adx.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-adx.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+adx +//@run-native #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86 { diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs index 8936ae8e91268..ba51dcea35cc6 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+aes,+vaes,+avx512f +//@run-native use core::mem::transmute; #[cfg(target_arch = "x86")] @@ -11,7 +12,6 @@ use std::arch::x86_64::*; fn main() { assert!(is_x86_feature_detected!("aes")); assert!(is_x86_feature_detected!("vaes")); - assert!(is_x86_feature_detected!("avx512f")); unsafe { test_aes(); @@ -86,7 +86,7 @@ unsafe fn test_aes() { // be interpreted as integers; signedness does not make sense for them, but // __m128i happens to be defined in terms of signed integers. #[allow(overflowing_literals)] -#[target_feature(enable = "vaes,avx512f")] +#[target_feature(enable = "vaes")] unsafe fn test_vaes() { #[target_feature(enable = "avx")] unsafe fn get_a256() -> __m256i { @@ -177,6 +177,12 @@ unsafe fn test_vaes() { } test_mm256_aesenclast_epi128(); + // The tests below require avx512. + if !is_x86_feature_detected!("avx512f") { + println!("warning: skipping avx512 tests"); + return; + } + #[target_feature(enable = "avx512f")] unsafe fn get_a512() -> __m512i { // Constants are random diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs index 9f7c12c4393b5..8709a17e8aeb4 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+avx +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs index de1abc818420c..0c88dbef43f87 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+avx2 +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs index 31f47b57fd285..0541e9a6cc6e0 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512bitalg,+avx512vpopcntdq,+avx512vnni,+avx512vbmi +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; @@ -9,6 +10,13 @@ use std::arch::x86_64::*; use std::mem::transmute; fn main() { + if !is_x86_feature_detected!("avx512f") { + // GH runners don't have this, but we still want to run this natively if + // the machine happens to have gfni. So we bail out dynamically. + println!("warning: skipping AVX512 tests"); + return; + } + assert!(is_x86_feature_detected!("avx512f")); assert!(is_x86_feature_detected!("avx512vl")); assert!(is_x86_feature_detected!("avx512bw")); diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-bmi.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-bmi.rs index 030258f21fa51..d6c05b601f4eb 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-bmi.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-bmi.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+bmi1,+bmi2 +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs index 48958ef581096..ef0fd62da5f3f 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+gfni,+avx512f +//@run-native // The constants in the tests below are just bit patterns. They should not // be interpreted as integers; signedness does not make sense for them, but @@ -20,8 +21,14 @@ const CONSTANT_BYTE: i32 = 0x63; fn main() { // Mostly copied from library/stdarch/crates/core_arch/src/x86/gfni.rs - assert!(is_x86_feature_detected!("avx512f")); - assert!(is_x86_feature_detected!("gfni")); + assert!(is_x86_feature_detected!("avx")); + + if !is_x86_feature_detected!("gfni") { + // GH runners don't have this, but we still want to run this natively if + // the machine happens to have gfni. So we bail out dynamically. + println!("warning: skipping gfni tests"); + return; + } unsafe { let byte_mul_test_data = generate_byte_mul_test_data(); @@ -29,15 +36,20 @@ fn main() { let affine_mul_test_data_constant = generate_affine_mul_test_data(CONSTANT_BYTE as u8); let inv_tests_data = generate_inv_tests_data(); - test_mm512_gf2p8mul_epi8(&byte_mul_test_data); test_mm256_gf2p8mul_epi8(&byte_mul_test_data); test_mm_gf2p8mul_epi8(&byte_mul_test_data); - test_mm512_gf2p8affine_epi64_epi8(&byte_mul_test_data, &affine_mul_test_data_identity); test_mm256_gf2p8affine_epi64_epi8(&byte_mul_test_data, &affine_mul_test_data_identity); test_mm_gf2p8affine_epi64_epi8(&byte_mul_test_data, &affine_mul_test_data_identity); - test_mm512_gf2p8affineinv_epi64_epi8(&inv_tests_data, &affine_mul_test_data_constant); test_mm256_gf2p8affineinv_epi64_epi8(&inv_tests_data, &affine_mul_test_data_constant); test_mm_gf2p8affineinv_epi64_epi8(&inv_tests_data, &affine_mul_test_data_constant); + + if is_x86_feature_detected!("avx512f") { + test_mm512_gf2p8mul_epi8(&byte_mul_test_data); + test_mm512_gf2p8affine_epi64_epi8(&byte_mul_test_data, &affine_mul_test_data_identity); + test_mm512_gf2p8affineinv_epi64_epi8(&inv_tests_data, &affine_mul_test_data_constant); + } else { + println!("warning: skipping avx512 tests"); + } } } diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs index 6051987f8d4c1..50ce9928ab7ed 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pclmulqdq.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+pclmulqdq +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs index 9136b5eda3870..f42c6db676839 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs @@ -1,5 +1,6 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 +//@run-native #![allow(unnecessary_transmutes)] #[cfg(target_arch = "x86")] diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs index 570da30f0b622..8e4b284b1d150 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs @@ -1,5 +1,6 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 +//@run-native #![allow(unnecessary_transmutes)] #[cfg(target_arch = "x86")] diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs index 10842160abdc6..e226f3512ac6e 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse3-ssse3.rs @@ -2,6 +2,7 @@ //@only-target: x86_64 i686 // SSSE3 implicitly enables SSE3 //@compile-flags: -C target-feature=+ssse3 +//@run-native use core::mem::transmute; #[cfg(target_arch = "x86")] diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs index 7331c6ed0db33..48510b46ff327 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse41.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+sse4.1 +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs index 30908baa6c15e..c998fe800df45 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs @@ -1,6 +1,7 @@ // We're testing x86 target specific features //@only-target: x86_64 i686 //@compile-flags: -C target-feature=+sse4.2 +//@run-native #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs index e2a045bf81ff1..5ceaf405f4040 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs @@ -3,6 +3,7 @@ //@only-target: x86_64 i686 //@[avx512]compile-flags: -C target-feature=+vpclmulqdq,+avx512f //@[avx]compile-flags: -C target-feature=+vpclmulqdq,+avx2 +//@run-native // The constants in the tests below are just bit patterns. They should not // be interpreted as integers; signedness does not make sense for them, but diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs index a18b6d01524e8..9745a437eccb6 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86.rs @@ -1,4 +1,6 @@ -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +//@only-target: x86_64 i686 +//@run-native + mod x86 { #[cfg(target_arch = "x86")] use core::arch::x86 as arch; @@ -84,7 +86,6 @@ mod x86_64 { } fn main() { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] x86::main(); #[cfg(target_arch = "x86_64")] x86_64::main(); From a67266628172a3459d87f6261ef54633c8bd9340 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 27 Jun 2026 15:39:29 +0200 Subject: [PATCH 72/77] run aarch64 intrinsic tests natively --- .../miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs | 1 + .../miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs | 1 + .../miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs index 1345924beecf0..c640dde5afaf5 100644 --- a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs +++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-aes.rs @@ -1,6 +1,7 @@ // We're testing aarch64 AES target specific features. //@only-target: aarch64 //@compile-flags: -C target-feature=+neon,+aes +//@run-native use std::arch::aarch64::*; use std::arch::is_aarch64_feature_detected; diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs index 849f99ee36cce..8d50d152f2ebe 100644 --- a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs +++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-crc32.rs @@ -1,6 +1,7 @@ // We're testing aarch64 CRC32 target specific features //@only-target: aarch64 //@compile-flags: -C target-feature=+crc +//@run-native use std::arch::aarch64::*; use std::arch::is_aarch64_feature_detected; diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs index 884f8eff41bdb..f2fd4b0c7f713 100644 --- a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs +++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs @@ -1,6 +1,7 @@ // We're testing aarch64 target specific features //@only-target: aarch64 //@compile-flags: -C target-feature=+neon +//@run-native use std::arch::aarch64::*; use std::arch::is_aarch64_feature_detected; From 21dfe67a80cbf9ff42bd2b62af42653dba9c8335 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 27 Jun 2026 16:54:44 +0200 Subject: [PATCH 73/77] fix bug in `mpsadbw` the 256-bit implementation actually takes a 6-bit IMM and uses the low 3 bits for the first 128-bit chunk, the next 3 bits for the second 128-bit chunk. Previously we only used the low 3 bits for both chunks. --- src/tools/miri/src/shims/x86/mod.rs | 22 ++++++++++++------- .../pass/shims/x86/intrinsics-x86-avx2.rs | 18 ++++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 64b5b786c6c08..b3a8291b9361b 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -879,33 +879,39 @@ fn mpsadbw<'tcx>( assert_eq!(left.layout.size, dest.layout.size); let (num_chunks, op_items_per_chunk, left) = split_simd_to_128bit_chunks(ecx, left)?; + assert!(num_chunks <= 2); + let (_, _, right) = split_simd_to_128bit_chunks(ecx, right)?; let (_, dest_items_per_chunk, dest) = split_simd_to_128bit_chunks(ecx, dest)?; assert_eq!(op_items_per_chunk, dest_items_per_chunk.strict_mul(2)); let imm = ecx.read_scalar(imm)?.to_uint(imm.layout.size)?; - // Bit 2 of `imm` specifies the offset for indices of `left`. - // The offset is 0 when the bit is 0 or 4 when the bit is 1. - let left_offset = u64::try_from((imm >> 2) & 1).unwrap().strict_mul(4); - // Bits 0..=1 of `imm` specify the offset for indices of - // `right` in blocks of 4 elements. - let right_offset = u64::try_from(imm & 0b11).unwrap().strict_mul(4); for i in 0..num_chunks { let left = ecx.project_index(&left, i)?; let right = ecx.project_index(&right, i)?; let dest = ecx.project_index(&dest, i)?; + // The first 128-bit chunk uses the low 3 bits of IMM, the second chunk uses bits 3..6. + let lane_imm = imm.strict_shr(i.strict_mul(3).try_into().unwrap()); + + // Bit 2 of `lane_imm` specifies the offset for indices of `left`. + // The offset is 0 when the bit is 0 or 4 when the bit is 1. + let left_base = u64::try_from((lane_imm >> 2) & 1).unwrap().strict_mul(4); + // Bits 0..=1 of `lane_imm` specify the offset for indices of + // `right` in blocks of 4 elements. + let right_base = u64::try_from(lane_imm & 0b11).unwrap().strict_mul(4); + for j in 0..dest_items_per_chunk { - let left_offset = left_offset.strict_add(j); + let left_offset = left_base.strict_add(j); let mut res: u16 = 0; for k in 0..4 { let left = ecx .read_scalar(&ecx.project_index(&left, left_offset.strict_add(k))?)? .to_u8()?; let right = ecx - .read_scalar(&ecx.project_index(&right, right_offset.strict_add(k))?)? + .read_scalar(&ecx.project_index(&right, right_base.strict_add(k))?)? .to_u8()?; res = res.strict_add(left.abs_diff(right).into()); } diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs index 0c88dbef43f87..7fe75254c2dd8 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx2.rs @@ -1069,23 +1069,31 @@ unsafe fn test_avx2() { 18, 20, 22, 24, 26, 28, 30, ); - let r = _mm256_mpsadbw_epu8::<0b000>(a, a); + let r = _mm256_mpsadbw_epu8::<0b00000>(a, a); let e = _mm256_setr_epi16(0, 4, 8, 12, 16, 20, 24, 28, 0, 8, 16, 24, 32, 40, 48, 56); assert_eq_m256i(r, e); - let r = _mm256_mpsadbw_epu8::<0b001>(a, a); + let r = _mm256_mpsadbw_epu8::<0b001001>(a, a); let e = _mm256_setr_epi16(16, 12, 8, 4, 0, 4, 8, 12, 32, 24, 16, 8, 0, 8, 16, 24); assert_eq_m256i(r, e); - let r = _mm256_mpsadbw_epu8::<0b100>(a, a); + let r = _mm256_mpsadbw_epu8::<0b000001>(a, a); + let e = _mm256_setr_epi16(16, 12, 8, 4, 0, 4, 8, 12, 0, 8, 16, 24, 32, 40, 48, 56); + assert_eq_m256i(r, e); + + let r = _mm256_mpsadbw_epu8::<0b001000>(a, a); + let e = _mm256_setr_epi16(0, 4, 8, 12, 16, 20, 24, 28, 32, 24, 16, 8, 0, 8, 16, 24); + assert_eq_m256i(r, e); + + let r = _mm256_mpsadbw_epu8::<0b100100>(a, a); let e = _mm256_setr_epi16(16, 20, 24, 28, 32, 36, 40, 44, 32, 40, 48, 56, 64, 72, 80, 88); assert_eq_m256i(r, e); - let r = _mm256_mpsadbw_epu8::<0b101>(a, a); + let r = _mm256_mpsadbw_epu8::<0b101101>(a, a); let e = _mm256_setr_epi16(0, 4, 8, 12, 16, 20, 24, 28, 0, 8, 16, 24, 32, 40, 48, 56); assert_eq_m256i(r, e); - let r = _mm256_mpsadbw_epu8::<0b111>(a, a); + let r = _mm256_mpsadbw_epu8::<0b111111>(a, a); let e = _mm256_setr_epi16(32, 28, 24, 20, 16, 12, 8, 4, 64, 56, 48, 40, 32, 24, 16, 8); assert_eq_m256i(r, e); } From 18c10cd1aa1d624824bf109e06eb408f24548e0e Mon Sep 17 00:00:00 2001 From: mehdiakiki Date: Sat, 20 Jun 2026 18:27:17 -0400 Subject: [PATCH 74/77] Adds RmetaLinkCache a per-link cache that uses path as the key of decoded lib.rmeta-link archive members, and routes add_archive read through it so each rlib link metadata is decoded at most once per link. This is a demand from a previous discussion and we split it out as its own PR. It gives that PR a decode once path tp read instead of reparsing each rlib per crate once native_lib_filenames moves to a link time read. --- .../rustc_codegen_ssa/src/back/archive.rs | 26 +++++++++++++------ compiler/rustc_codegen_ssa/src/back/link.rs | 16 ++++++++++-- .../rustc_codegen_ssa/src/back/rmeta_link.rs | 18 ++++++++++++- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index bdf346d8e69d2..4fc516b244857 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -22,7 +22,7 @@ use rustc_target::spec::Arch; use tracing::trace; use super::metadata::{create_compressed_metadata_file, search_for_section}; -use super::rmeta_link; +use super::rmeta_link::{self, RmetaLinkCache}; use super::symbol_edit::{apply_edits, collect_internal_names}; use crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs @@ -311,7 +311,7 @@ fn find_binutils_dlltool(sess: &Session) -> OsString { } pub enum AddArchiveKind<'a> { - Rlib(/*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool), + Rlib(&'a mut RmetaLinkCache, /*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool), Other, } @@ -466,7 +466,11 @@ pub fn try_extract_macho_fat_archive( } impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { - fn add_archive(&mut self, archive_path: &Path, ar_kind: AddArchiveKind<'_>) -> io::Result<()> { + fn add_archive( + &mut self, + archive_path: &Path, + mut ar_kind: AddArchiveKind<'_>, + ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") && let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? @@ -481,8 +485,14 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; let archive = ArchiveFile::parse(&*archive_map) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let metadata_link = match ar_kind { - AddArchiveKind::Rlib(..) => rmeta_link::read(&archive, &archive_map, &archive_path), + let skip = match &ar_kind { + AddArchiveKind::Rlib(_, skip) => Some(*skip), + AddArchiveKind::Other => None, + }; + let metadata_link = match &mut ar_kind { + AddArchiveKind::Rlib(cache, _) => cache.get_or_insert_with(&archive_path, || { + rmeta_link::read(&archive, &archive_map, &archive_path) + }), AddArchiveKind::Other => None, }; let archive_index = self.src_archives.len(); @@ -512,9 +522,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { } else { ArchiveEntryKind::Other }; - let drop = match ar_kind { - AddArchiveKind::Rlib(skip) => skip(&file_name, kind), - AddArchiveKind::Other => false, + let drop = match skip { + Some(skip) => skip(&file_name, kind), + None => false, }; if !drop { let source = if entry.is_thin() { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 2c3ee1bae09f8..0f709247d2333 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -59,6 +59,7 @@ use super::archive::{ use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; +use super::rmeta_link::RmetaLinkCache; use super::rpath::{self, RPathConfig}; use super::{apple, rmeta_link, versioned_llvm_target}; use crate::base::needs_allocator_shim_for_linking; @@ -86,6 +87,7 @@ pub fn link_binary( let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); let mut tempfiles_for_stdout_output: Vec = Vec::new(); + let mut rmeta_link_cache = RmetaLinkCache::default(); for &crate_type in &crate_info.crate_types { // Ignore executable crates if we have -Z no-codegen, as they will error. if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen()) @@ -139,6 +141,7 @@ pub fn link_binary( link_staticlib( sess, archive_builder_builder, + &mut rmeta_link_cache, &compiled_modules, &crate_info, &metadata, @@ -150,6 +153,7 @@ pub fn link_binary( link_natively( sess, archive_builder_builder, + &mut rmeta_link_cache, crate_type, &out_filename, &compiled_modules, @@ -502,6 +506,7 @@ fn link_rlib<'a>( fn link_staticlib( sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, compiled_modules: &CompiledModules, crate_info: &CrateInfo, metadata: &EncodedMetadata, @@ -531,7 +536,7 @@ fn link_staticlib( let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); ab.add_archive( path, - AddArchiveKind::Rlib(&|fname: &str, entry_kind| { + AddArchiveKind::Rlib(rmeta_link_cache, &|fname: &str, entry_kind| { // Ignore metadata and rmeta-link files. if fname == METADATA_FILENAME || fname == rmeta_link::FILENAME { return true; @@ -939,6 +944,7 @@ fn report_linker_output( fn link_natively( sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_type: CrateType, out_filename: &Path, compiled_modules: &CompiledModules, @@ -965,6 +971,7 @@ fn link_natively( flavor, sess, archive_builder_builder, + rmeta_link_cache, crate_type, tmpdir, temp_filename, @@ -2491,6 +2498,7 @@ fn linker_with_args( flavor: LinkerFlavor, sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_type: CrateType, tmpdir: &Path, out_filename: &Path, @@ -2619,6 +2627,7 @@ fn linker_with_args( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, crate_type, tmpdir, @@ -3055,6 +3064,7 @@ fn add_upstream_rust_crates( cmd: &mut dyn Linker, sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_info: &CrateInfo, crate_type: CrateType, tmpdir: &Path, @@ -3107,6 +3117,7 @@ fn add_upstream_rust_crates( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, tmpdir, cnum, @@ -3238,6 +3249,7 @@ fn add_static_crate( cmd: &mut dyn Linker, sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_info: &CrateInfo, tmpdir: &Path, cnum: CrateNum, @@ -3268,7 +3280,7 @@ fn add_static_crate( let mut archive = archive_builder_builder.new_archive_builder(sess); if let Err(error) = archive.add_archive( cratepath, - AddArchiveKind::Rlib(&|f, entry_kind| { + AddArchiveKind::Rlib(rmeta_link_cache, &|f, entry_kind| { if f == METADATA_FILENAME || f == rmeta_link::FILENAME { return true; } diff --git a/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs b/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs index 68b23ca9ac5cb..58da783277dfe 100644 --- a/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs +++ b/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs @@ -2,9 +2,10 @@ //! and potentially other data collected and used when building or linking a rlib. //! See . -use std::path::Path; +use std::path::{Path, PathBuf}; use object::read::archive::ArchiveFile; +use rustc_data_structures::fx::FxHashMap; use rustc_serialize::opaque::mem_encoder::MemEncoder; use rustc_serialize::opaque::{MAGIC_END_BYTES, MemDecoder}; use rustc_serialize::{Decodable, Encodable}; @@ -54,3 +55,18 @@ pub fn read_from_data(archive_data: &[u8], rlib_path: &Path) -> Option>, +} + +impl RmetaLinkCache { + pub fn get_or_insert_with( + &mut self, + rlib_path: &Path, + load: impl FnOnce() -> Option, + ) -> Option<&RmetaLink> { + self.cache.entry(rlib_path.to_path_buf()).or_insert_with(load).as_ref() + } +} From 94888f003a2e436f788965cdedfc6a5efc55bed5 Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Sat, 27 Jun 2026 17:09:13 +0100 Subject: [PATCH 75/77] update bless output Signed-off-by: Emmanuel Ugwu --- tests/ui/lint/lint-stability.stderr | 95 ++++++++++++++++------------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr index fd57908a77b53..67f6804d7c076 100644 --- a/tests/ui/lint/lint-stability.stderr +++ b/tests/ui/lint/lint-stability.stderr @@ -8,7 +8,16 @@ LL | extern crate stability_cfg2; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:45:9 + --> $DIR/lint-stability.rs:21:34 + | +LL | fn test_foreign_type(_: &mut UnstableForeignType) { + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `unstable_test_feature` + --> $DIR/lint-stability.rs:48:9 | LL | deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^ @@ -17,7 +26,7 @@ LL | deprecated_unstable(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:47:9 + --> $DIR/lint-stability.rs:50:9 | LL | Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +35,7 @@ LL | Trait::trait_deprecated_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:49:9 + --> $DIR/lint-stability.rs:52:9 | LL | ::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +44,7 @@ LL | ::trait_deprecated_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:52:9 + --> $DIR/lint-stability.rs:55:9 | LL | deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -44,7 +53,7 @@ LL | deprecated_unstable_text(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:54:9 + --> $DIR/lint-stability.rs:57:9 | LL | Trait::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +62,7 @@ LL | Trait::trait_deprecated_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:56:9 + --> $DIR/lint-stability.rs:59:9 | LL | ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +71,7 @@ LL | ::trait_deprecated_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:59:9 + --> $DIR/lint-stability.rs:62:9 | LL | unstable(); | ^^^^^^^^ @@ -71,7 +80,7 @@ LL | unstable(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:60:9 + --> $DIR/lint-stability.rs:63:9 | LL | Trait::trait_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +89,7 @@ LL | Trait::trait_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:61:9 + --> $DIR/lint-stability.rs:64:9 | LL | ::trait_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +98,7 @@ LL | ::trait_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature`: text - --> $DIR/lint-stability.rs:63:9 + --> $DIR/lint-stability.rs:66:9 | LL | unstable_text(); | ^^^^^^^^^^^^^ @@ -98,7 +107,7 @@ LL | unstable_text(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature`: text - --> $DIR/lint-stability.rs:65:9 + --> $DIR/lint-stability.rs:68:9 | LL | Trait::trait_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +116,7 @@ LL | Trait::trait_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature`: text - --> $DIR/lint-stability.rs:67:9 + --> $DIR/lint-stability.rs:70:9 | LL | ::trait_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,7 +125,7 @@ LL | ::trait_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:99:17 + --> $DIR/lint-stability.rs:102:17 | LL | let _ = DeprecatedUnstableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,7 +134,7 @@ LL | let _ = DeprecatedUnstableStruct { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:103:17 + --> $DIR/lint-stability.rs:106:17 | LL | let _ = UnstableStruct { i: 0 }; | ^^^^^^^^^^^^^^ @@ -134,7 +143,7 @@ LL | let _ = UnstableStruct { i: 0 }; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:107:17 + --> $DIR/lint-stability.rs:110:17 | LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +152,7 @@ LL | let _ = DeprecatedUnstableUnitStruct; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:109:17 + --> $DIR/lint-stability.rs:112:17 | LL | let _ = UnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^ @@ -152,7 +161,7 @@ LL | let _ = UnstableUnitStruct; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:113:17 + --> $DIR/lint-stability.rs:116:17 | LL | let _ = Enum::DeprecatedUnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -161,7 +170,7 @@ LL | let _ = Enum::DeprecatedUnstableVariant; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:115:17 + --> $DIR/lint-stability.rs:118:17 | LL | let _ = Enum::UnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^ @@ -170,7 +179,7 @@ LL | let _ = Enum::UnstableVariant; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:119:17 + --> $DIR/lint-stability.rs:122:17 | LL | let _ = DeprecatedUnstableTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +188,7 @@ LL | let _ = DeprecatedUnstableTupleStruct (1); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:121:17 + --> $DIR/lint-stability.rs:124:17 | LL | let _ = UnstableTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^ @@ -188,7 +197,7 @@ LL | let _ = UnstableTupleStruct (1); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:130:25 + --> $DIR/lint-stability.rs:133:25 | LL | macro_test_arg!(deprecated_unstable_text()); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +206,7 @@ LL | macro_test_arg!(deprecated_unstable_text()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:144:9 + --> $DIR/lint-stability.rs:147:9 | LL | Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,7 +215,7 @@ LL | Trait::trait_deprecated_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:146:9 + --> $DIR/lint-stability.rs:149:9 | LL | ::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -215,7 +224,7 @@ LL | ::trait_deprecated_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:148:9 + --> $DIR/lint-stability.rs:151:9 | LL | Trait::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -224,7 +233,7 @@ LL | Trait::trait_deprecated_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:150:9 + --> $DIR/lint-stability.rs:153:9 | LL | ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +242,7 @@ LL | ::trait_deprecated_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:152:9 + --> $DIR/lint-stability.rs:155:9 | LL | Trait::trait_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^ @@ -242,7 +251,7 @@ LL | Trait::trait_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:153:9 + --> $DIR/lint-stability.rs:156:9 | LL | ::trait_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -251,7 +260,7 @@ LL | ::trait_unstable(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature`: text - --> $DIR/lint-stability.rs:154:9 + --> $DIR/lint-stability.rs:157:9 | LL | Trait::trait_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -260,7 +269,7 @@ LL | Trait::trait_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature`: text - --> $DIR/lint-stability.rs:156:9 + --> $DIR/lint-stability.rs:159:9 | LL | ::trait_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -269,7 +278,7 @@ LL | ::trait_unstable_text(&foo); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:172:10 + --> $DIR/lint-stability.rs:175:10 | LL | impl UnstableTrait for S { } | ^^^^^^^^^^^^^ @@ -278,7 +287,7 @@ LL | impl UnstableTrait for S { } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:174:24 + --> $DIR/lint-stability.rs:177:24 | LL | trait LocalTrait : UnstableTrait { } | ^^^^^^^^^^^^^ @@ -287,7 +296,7 @@ LL | trait LocalTrait : UnstableTrait { } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:179:9 + --> $DIR/lint-stability.rs:182:9 | LL | fn trait_unstable(&self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -296,7 +305,7 @@ LL | fn trait_unstable(&self) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:184:5 + --> $DIR/lint-stability.rs:187:5 | LL | extern crate inherited_stability; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -305,7 +314,7 @@ LL | extern crate inherited_stability; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:185:9 + --> $DIR/lint-stability.rs:188:9 | LL | use self::inherited_stability::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -314,7 +323,7 @@ LL | use self::inherited_stability::*; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:188:9 + --> $DIR/lint-stability.rs:191:9 | LL | unstable(); | ^^^^^^^^ @@ -323,7 +332,7 @@ LL | unstable(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:191:9 + --> $DIR/lint-stability.rs:194:9 | LL | stable_mod::unstable(); | ^^^^^^^^^^^^^^^^^^^^ @@ -332,7 +341,7 @@ LL | stable_mod::unstable(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:194:9 + --> $DIR/lint-stability.rs:197:9 | LL | unstable_mod::deprecated(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -341,7 +350,7 @@ LL | unstable_mod::deprecated(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:195:9 + --> $DIR/lint-stability.rs:198:9 | LL | unstable_mod::unstable(); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +359,7 @@ LL | unstable_mod::unstable(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:197:17 + --> $DIR/lint-stability.rs:200:17 | LL | let _ = Unstable::UnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -359,7 +368,7 @@ LL | let _ = Unstable::UnstableVariant; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:198:17 + --> $DIR/lint-stability.rs:201:17 | LL | let _ = Unstable::StableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -368,7 +377,7 @@ LL | let _ = Unstable::StableVariant; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:88:48 + --> $DIR/lint-stability.rs:91:48 | LL | struct S1(T::TypeUnstable); | ^^^^^^^^^^^^^^^ @@ -377,7 +386,7 @@ LL | struct S1(T::TypeUnstable); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:92:13 + --> $DIR/lint-stability.rs:95:13 | LL | TypeUnstable = u8, | ^^^^^^^^^^^^^^^^^ @@ -385,6 +394,6 @@ LL | TypeUnstable = u8, = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 43 previous errors +error: aborting due to 44 previous errors For more information about this error, try `rustc --explain E0658`. From 075f549a564287065b631a8d8a769dd0fc2864f1 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 22 Jun 2026 22:32:58 +0200 Subject: [PATCH 76/77] add `vqdmulh*` aarch64 intrinsics --- src/tools/miri/src/shims/aarch64.rs | 39 +++++++++++++++ .../shims/aarch64/intrinsics-aarch64-neon.rs | 49 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/src/tools/miri/src/shims/aarch64.rs b/src/tools/miri/src/shims/aarch64.rs index deab856b3e24f..3d8946fb36720 100644 --- a/src/tools/miri/src/shims/aarch64.rs +++ b/src/tools/miri/src/shims/aarch64.rs @@ -146,6 +146,45 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } + // Signed saturating doubling multiply returning the high half. + // + // Used by the `vqdmulh*` functions. + // + // This LLVM intrinsic multiplies the values of corresponding elements of the two source + // vector registers (which are signed integers), doubles the results, places the most significant half of the + // final results (using a saturating cast to fit the element type) into a vector, and writes the vector to the destination register. + // + // https://developer.arm.com/architectures/instruction-sets/intrinsics#f:@navigationhierarchiessimdisa=[Neon]&q=vqdmulh + name if name.starts_with("neon.sqdmulh.") => { + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; + + let (left, left_len) = this.project_to_simd(left)?; + let (right, right_len) = this.project_to_simd(right)?; + let (dest, dest_len) = this.project_to_simd(dest)?; + assert_eq!(left_len, right_len); + assert_eq!(left_len, dest_len); + + let elem_size = dest.layout.field(this, 0).size; + let bits = elem_size.bits(); + let min = elem_size.signed_int_min(); + let max = elem_size.signed_int_max(); + + for i in 0..dest_len { + let a = this.read_scalar(&this.project_index(&left, i)?)?.to_int(elem_size)?; + let b = this.read_scalar(&this.project_index(&right, i)?)?.to_int(elem_size)?; + + // Uses i128 arithmetic, which cannot overflow because the intrinsic takes at most i32. + let doubled = a.strict_mul(b).strict_mul(2); + let res = (doubled >> bits).clamp(min, max); + + this.write_scalar( + Scalar::from_int(res, elem_size), + &this.project_index(&dest, i)?, + )?; + } + } + // Vector table lookup: each index selects a byte from the 16-byte table, out-of-range -> 0. // Used to implement vtbl1_u8 function. // LLVM does not have a portable shuffle that takes non-const indices diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs index 884f8eff41bdb..9a400b61e2e59 100644 --- a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs +++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs @@ -14,6 +14,7 @@ fn main() { test_tbl1_v16i8_basic(); test_vpadd(); test_vpaddl(); + test_vqdmulh(); } } @@ -157,3 +158,51 @@ unsafe fn test_vpaddl() { vst1q_u64(r.as_mut_ptr(), vpaddlq_u32(a)); assert_eq!(r, e); } + +#[target_feature(enable = "neon")] +unsafe fn test_vqdmulh() { + let a = vld1_s32([i32::MIN, i32::MAX].as_ptr()); + let r: [i32; 2] = transmute(vqdmulh_n_s32(a, i32::MIN)); + assert_eq!(r, [i32::MAX, -i32::MAX]); + + // This is the actual calculation that happens. + let product = i32::MIN as i128 * i32::MIN as i128 * 2; + assert_eq!(i32::MAX, (product >> 32).clamp(i32::MIN as i128, i32::MAX as i128) as i32); + + let product = i32::MAX as i128 * i32::MIN as i128 * 2; + assert_eq!(-i32::MAX, (product >> 32).clamp(i32::MIN as i128, i32::MAX as i128) as i32); + + let b = vld1_s32([123, i32::MIN].as_ptr()); + let r: [i32; 2] = transmute(vqdmulh_s32(a, b)); + assert_eq!(r, [-123, -i32::MAX]); + + // Wider 32-bit versions. + let a = vld1q_s32([0x4000_0000, -0x4000_0000, i32::MIN, i32::MAX].as_ptr()); + + let b = vld1q_s32([123, 456, 0x4000_0000, 789].as_ptr()); + let r: [i32; 4] = transmute(vqdmulhq_s32(a, b)); + assert_eq!(r, [61, -228, -1073741824, 788]); + + let r: [i32; 4] = transmute(vqdmulhq_n_s32(a, 0x4000_0000)); + assert_eq!(r, [536870912, -536870912, -1073741824, 1073741823]); + + // 16-bit versions. + + let a = vld1_s16([i16::MIN, i16::MAX, 0, 16384].as_ptr()); + let r: [i16; 4] = transmute(vqdmulh_n_s16(a, i16::MIN)); + assert_eq!(r, [i16::MAX, -i16::MAX, 0, -16384]); + + let b = vld1_s16([123, i16::MIN, 456, 789].as_ptr()); + let r: [i16; 4] = transmute(vqdmulh_s16(a, b)); + assert_eq!(r, [-123, -i16::MAX, 0, 394]); + + // Wider 16-bit versions. + + let a = vld1q_s16([i16::MIN, i16::MAX, 0, 16384, -16384, 8192, 1, -1].as_ptr()); + let b = vld1q_s16([123, 456, 789, i16::MIN, 1, 2, 3, 4].as_ptr()); + let r: [i16; 8] = transmute(vqdmulhq_s16(a, b)); + assert_eq!(r, [-123, 455, 0, -16384, -1, 0, 0, -1]); + + let r: [i16; 8] = transmute(vqdmulhq_n_s16(a, i16::MIN)); + assert_eq!(r, [32767, -32767, 0, -16384, 16384, -8192, -1, 1]); +} From 3515461784dd940137379fe8d86e07d6783c5817 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 27 Jun 2026 23:14:21 +0200 Subject: [PATCH 77/77] use `"llvm.prefetch.p0"` instead of `"llvm.prefetch"` LLVM updated the name, the old one still works but stdarch is now using the new one --- compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs | 2 +- compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index 2dee9176936fd..9ec84d135dc8f 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -19,7 +19,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( } match intrinsic { - "llvm.prefetch" => { + "llvm.prefetch.p0" => { // Nothing to do. This is merely a perf hint. } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs index d58697f1bf270..41efe3e8209bf 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs @@ -1044,7 +1044,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function #[cfg(feature = "master")] pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> { let gcc_name = match name { - "llvm.prefetch" => { + "llvm.prefetch.p0" => { let gcc_name = "__builtin_prefetch"; let func = cx.context.get_builtin_function(gcc_name); cx.functions.borrow_mut().insert(gcc_name.to_string(), func); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 0b03d6862ca84..4ec398a6ec27d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -402,7 +402,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let ptr = args[0].immediate(); let locality = fn_args.const_at(1).to_leaf().to_i32(); self.call_intrinsic( - "llvm.prefetch", + "llvm.prefetch.p0", &[self.val_ty(ptr)], &[ ptr, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index e4daab7a2005d..5fd86769e96b5 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -789,7 +789,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // LLVM intrinsics - "llvm.prefetch" => { + "llvm.prefetch.p0" => { let [p, rw, loc, ty] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;