From 0e878d605ba50b8c574ed058fb173c2a778af4bc Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 6 Aug 2026 13:48:05 +0000 Subject: [PATCH] mir: prohibit projection into scalable vec --- compiler/rustc_mir_transform/src/sroa.rs | 4 ++- compiler/rustc_mir_transform/src/validate.rs | 2 +- .../crates/core_arch/src/aarch64/sve/mod.rs | 8 ++--- ...roa.bar.ScalarReplacementOfAggregates.diff | 32 +++++++++++++++++++ ...roa.foo.ScalarReplacementOfAggregates.diff | 32 +++++++++++++++++++ tests/mir-opt/sroa/scalable_sroa.rs | 30 +++++++++++++++++ tests/ui/scalable-vectors/auxiliary/simple.rs | 13 ++++++++ .../project-into-field-extern.rs | 21 ++++++++++++ .../project-into-field-extern.stderr | 9 ++++++ .../ui/scalable-vectors/project-into-field.rs | 24 ++++++++++++++ .../project-into-field.stderr | 8 +++++ 11 files changed, 177 insertions(+), 6 deletions(-) create mode 100644 tests/mir-opt/sroa/scalable_sroa.bar.ScalarReplacementOfAggregates.diff create mode 100644 tests/mir-opt/sroa/scalable_sroa.foo.ScalarReplacementOfAggregates.diff create mode 100644 tests/mir-opt/sroa/scalable_sroa.rs create mode 100644 tests/ui/scalable-vectors/auxiliary/simple.rs create mode 100644 tests/ui/scalable-vectors/project-into-field-extern.rs create mode 100644 tests/ui/scalable-vectors/project-into-field-extern.stderr create mode 100644 tests/ui/scalable-vectors/project-into-field.rs create mode 100644 tests/ui/scalable-vectors/project-into-field.stderr diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index b16336fb9150c..f4f90372b4a8d 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -69,7 +69,9 @@ fn escaping_locals<'tcx>( return true; } if let ty::Adt(def, _args) = ty.kind() - && (def.repr().simd() || tcx.is_lang_item(def.did(), LangItem::DynMetadata)) + && (def.repr().simd() + || def.repr().scalable() + || tcx.is_lang_item(def.did(), LangItem::DynMetadata)) { // Exclude #[repr(simd)] types so that they are not de-optimized into an array // (MCP#838 banned projections into SIMD types, but if the value is unused diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 4413d5064bd14..af058fb4abb3b 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -707,7 +707,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } - if adt_def.repr().simd() { + if adt_def.repr().simd() || adt_def.repr().scalable() { self.fail( location, format!( 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 f11ca660b15e2..41fd12d3517b4 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/mod.rs @@ -39,7 +39,7 @@ impl SveInto for T { macro_rules! impl_sve_type { ($(($v:vis, $elem_type:ty, $name:ident, $elt:literal))*) => ($( #[doc = concat!("Scalable vector of type ", stringify!($elem_type))] - #[derive(Clone, Copy, Debug)] + #[derive(Clone, Copy)] #[rustc_scalable_vector($elt)] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] $v struct $name($elem_type); @@ -52,21 +52,21 @@ macro_rules! impl_sve_tuple_type { )*); (@ ($v:vis, $vec_type:ty, 2, $name:ident)) => ( #[doc = concat!("Two-element tuple of scalable vectors of type ", stringify!($vec_type))] - #[derive(Clone, Copy, Debug)] + #[derive(Clone, Copy)] #[rustc_scalable_vector] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] $v struct $name($vec_type, $vec_type); ); (@ ($v:vis, $vec_type:ty, 3, $name:ident)) => ( #[doc = concat!("Three-element tuple of scalable vectors of type ", stringify!($vec_type))] - #[derive(Clone, Copy, Debug)] + #[derive(Clone, Copy)] #[rustc_scalable_vector] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] $v struct $name($vec_type, $vec_type, $vec_type); ); (@ ($v:vis, $vec_type:ty, 4, $name:ident)) => ( #[doc = concat!("Four-element tuple of scalable vectors of type ", stringify!($vec_type))] - #[derive(Clone, Copy, Debug)] + #[derive(Clone, Copy)] #[rustc_scalable_vector] #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] $v struct $name($vec_type, $vec_type, $vec_type, $vec_type); diff --git a/tests/mir-opt/sroa/scalable_sroa.bar.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/scalable_sroa.bar.ScalarReplacementOfAggregates.diff new file mode 100644 index 0000000000000..fa4b14620b10e --- /dev/null +++ b/tests/mir-opt/sroa/scalable_sroa.bar.ScalarReplacementOfAggregates.diff @@ -0,0 +1,32 @@ +- // MIR for `bar` before ScalarReplacementOfAggregates ++ // MIR for `bar` after ScalarReplacementOfAggregates + + fn bar(_1: &[svuint32x2_t], _2: svuint32x2_t) -> () { + debug simds => _1; + debug _unused => _2; + let mut _0: (); + let _3: std::arch::aarch64::svuint32x2_t; + let _4: usize; + let mut _5: usize; + let mut _6: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = const 0_usize; + _5 = PtrMetadata(copy _1); + _6 = Lt(copy _4, copy _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + } + + bb1: { + _3 = copy (*_1)[_4]; + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/sroa/scalable_sroa.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/scalable_sroa.foo.ScalarReplacementOfAggregates.diff new file mode 100644 index 0000000000000..0aceea57e17a6 --- /dev/null +++ b/tests/mir-opt/sroa/scalable_sroa.foo.ScalarReplacementOfAggregates.diff @@ -0,0 +1,32 @@ +- // MIR for `foo` before ScalarReplacementOfAggregates ++ // MIR for `foo` after ScalarReplacementOfAggregates + + fn foo(_1: &[svuint32_t], _2: svuint32_t) -> () { + debug simds => _1; + debug _unused => _2; + let mut _0: (); + let _3: std::arch::aarch64::svuint32_t; + let _4: usize; + let mut _5: usize; + let mut _6: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = const 0_usize; + _5 = PtrMetadata(copy _1); + _6 = Lt(copy _4, copy _5); + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue]; + } + + bb1: { + _3 = copy (*_1)[_4]; + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/sroa/scalable_sroa.rs b/tests/mir-opt/sroa/scalable_sroa.rs new file mode 100644 index 0000000000000..a282bdae83265 --- /dev/null +++ b/tests/mir-opt/sroa/scalable_sroa.rs @@ -0,0 +1,30 @@ +//@ only-aarch64 +//@ needs-unwind +#![feature(stdarch_aarch64_sve)] + +// SRoA expands things even if they're unused +// + +use std::arch::aarch64::{svuint32_t, svuint32x2_t}; + +// EMIT_MIR scalable_sroa.foo.ScalarReplacementOfAggregates.diff +pub(crate) fn foo(simds: &[svuint32_t], _unused: svuint32_t) { + // CHECK-LABEL: fn foo + // CHECK-NOT: u32 + // CHECK: let [[SIMD:_.+]]: std::arch::aarch64::svuint32_t; + // CHECK-NOT: u32 + // CHECK: [[SIMD]] = copy (*_1)[0 of 1]; + // CHECK-NOT: u32 + let a = simds[0]; +} + +// EMIT_MIR scalable_sroa.bar.ScalarReplacementOfAggregates.diff +pub(crate) fn bar(simds: &[svuint32x2_t], _unused: svuint32x2_t) { + // CHECK-LABEL: fn bar + // CHECK-NOT: { , } + // CHECK: let [[SIMD:_.+]]: std::arch::aarch64::svuint32x2_t; + // CHECK-NOT: { , } + // CHECK: [[SIMD]] = copy (*_1)[0 of 1]; + // CHECK-NOT: { , } + let a = simds[0]; +} diff --git a/tests/ui/scalable-vectors/auxiliary/simple.rs b/tests/ui/scalable-vectors/auxiliary/simple.rs new file mode 100644 index 0000000000000..f6b677b7db620 --- /dev/null +++ b/tests/ui/scalable-vectors/auxiliary/simple.rs @@ -0,0 +1,13 @@ +//@ add-minicore +//@ compile-flags: -Copt-level=0 +//@ only-aarch64 +#![feature(no_core, rustc_attrs)] +#![no_std] +#![no_core] +#![crate_type = "lib"] +#![allow(internal_features)] + +extern crate minicore; + +#[rustc_scalable_vector(4)] +pub struct Sv(f32); diff --git a/tests/ui/scalable-vectors/project-into-field-extern.rs b/tests/ui/scalable-vectors/project-into-field-extern.rs new file mode 100644 index 0000000000000..db35ccaa1c5ed --- /dev/null +++ b/tests/ui/scalable-vectors/project-into-field-extern.rs @@ -0,0 +1,21 @@ +//@ add-minicore +//@ aux-build: simple.rs +//@ compile-flags: -Copt-level=0 +//@ check-fail +//@ only-aarch64 +#![feature(no_core, rustc_attrs)] +#![no_std] +#![no_core] +#![crate_type = "lib"] +#![allow(internal_features)] + +extern crate minicore; +extern crate simple; + +pub use simple::Sv; + +#[target_feature(enable = "sve")] +pub fn field(x: Sv) -> f32 { + x.0 + //~^ ERROR: field `0` of struct `Sv` is private +} diff --git a/tests/ui/scalable-vectors/project-into-field-extern.stderr b/tests/ui/scalable-vectors/project-into-field-extern.stderr new file mode 100644 index 0000000000000..38bc5f21b7c10 --- /dev/null +++ b/tests/ui/scalable-vectors/project-into-field-extern.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `0` of struct `Sv` is private + --> $DIR/project-into-field-extern.rs:19:7 + | +LL | x.0 + | ^ private field + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/scalable-vectors/project-into-field.rs b/tests/ui/scalable-vectors/project-into-field.rs new file mode 100644 index 0000000000000..4b829de8f2280 --- /dev/null +++ b/tests/ui/scalable-vectors/project-into-field.rs @@ -0,0 +1,24 @@ +//@ add-minicore +//@ build-fail +//@ compile-flags: -Copt-level=0 --target=aarch64-unknown-linux-gnu +//@ dont-check-compiler-stderr +//@ failure-status: 101 +//@ ignore-backends: gcc +//@ needs-llvm-components: aarch64 +#![feature(no_core, rustc_attrs)] +#![no_std] +#![no_core] +#![crate_type = "lib"] +#![allow(internal_features)] + +extern crate minicore; + +#[rustc_scalable_vector(4)] +pub struct Sv(f32); + +#[target_feature(enable = "sve")] +pub fn field(x: Sv) -> f32 { + x.0 + //~^ ERROR broken MIR in Item + //~| ERROR Projecting into SIMD type Sv is banned by MCP#838 +} diff --git a/tests/ui/scalable-vectors/project-into-field.stderr b/tests/ui/scalable-vectors/project-into-field.stderr new file mode 100644 index 0000000000000..7a13c17646a96 --- /dev/null +++ b/tests/ui/scalable-vectors/project-into-field.stderr @@ -0,0 +1,8 @@ +error: cannot project into scalable vector type `Sv` + --> $DIR/project-into-field.rs:18:5 + | +LL | x.0 + | ^^^ + +error: aborting due to 1 previous error +