diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index 8c5a1d8970922..bf14d5eb9a0a8 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -163,7 +163,13 @@ borrowck_returned_lifetime_wrong = borrowck_returned_ref_escaped = returns a reference to a captured variable which escapes the closure body -borrowck_simd_shuffle_last_const = last argument of `simd_shuffle` is required to be a `const` item +borrowck_simd_intrinsic_arg_const = + {$arg -> + [1] 1st + [2] 2nd + [3] 3rd + *[other] {$arg}th + } argument of `{$intrinsic}` is required to be a `const` item borrowck_suggest_create_freash_reborrow = consider reborrowing the `Pin` instead of moving it diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 1685624f24772..a055ce95e8ef3 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -454,8 +454,10 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { } #[derive(Diagnostic)] -#[diag(borrowck_simd_shuffle_last_const)] -pub(crate) struct SimdShuffleLastConst { +#[diag(borrowck_simd_intrinsic_arg_const)] +pub(crate) struct SimdIntrinsicArgConst { #[primary_span] pub span: Span, + pub arg: usize, + pub intrinsic: String, } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 81193902f9b32..75cc28bcab0bc 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -49,7 +49,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; -use crate::session_diagnostics::{MoveUnsized, SimdShuffleLastConst}; +use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; use crate::{ borrow_set::BorrowSet, constraints::{OutlivesConstraint, OutlivesConstraintSet}, @@ -1664,9 +1664,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let func_ty = func.ty(body, self.infcx.tcx); if let ty::FnDef(def_id, _) = *func_ty.kind() { - if let Some(sym::simd_shuffle) = self.tcx().intrinsic(def_id) { - if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) { - self.tcx().dcx().emit_err(SimdShuffleLastConst { span: term.source_info.span }); + // Some of the SIMD intrinsics are special: they need a particular argument to be a constant. + // (Eventually this should use const-generics, but those are not up for the task yet: + // https://github.com/rust-lang/rust/issues/85229.) + if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) = + self.tcx().intrinsic(def_id) + { + let idx = match name { + sym::simd_shuffle => 2, + _ => 1, + }; + if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) { + self.tcx().dcx().emit_err(SimdIntrinsicArgConst { + span: term.source_info.span, + arg: idx + 1, + intrinsic: name.to_string(), + }); } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 75d413dedad3e..00007110938e0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -864,8 +864,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .map(|(i, arg)| { // The indices passed to simd_shuffle in the // third argument must be constant. This is - // checked by const-qualification, which also - // promotes any complex rvalues to constants. + // checked by the type-checker. if i == 2 && intrinsic == sym::simd_shuffle { if let mir::Operand::Constant(constant) = &arg.node { let (llval, ty) = self.simd_shuffle_indices(bx, constant); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs deleted file mode 100644 index a5d2509d00051..0000000000000 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs +++ /dev/null @@ -1,47 +0,0 @@ -// compile-flags: -C no-prepopulate-passes - -#![crate_type = "lib"] - -#![feature(repr_simd, platform_intrinsics, min_const_generics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct M(pub f32, pub f32, pub f32, pub f32); - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct S([f32; N]); - -extern "platform-intrinsic" { - fn simd_extract(x: T, idx: u32) -> U; - fn simd_insert(x: T, idx: u32, b: U) -> T; -} - -// CHECK-LABEL: @extract_m -#[no_mangle] -pub unsafe fn extract_m(v: M, i: u32) -> f32 { - // CHECK: extractelement <4 x float> %{{v|1|2}}, i32 %i - simd_extract(v, i) -} - -// CHECK-LABEL: @extract_s -#[no_mangle] -pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 { - // CHECK: extractelement <4 x float> %{{v|1|2}}, i32 %i - simd_extract(v, i) -} - -// CHECK-LABEL: @insert_m -#[no_mangle] -pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M { - // CHECK: insertelement <4 x float> %{{v|0|1}}, float %j, i32 %i - simd_insert(v, i, j) -} - -// CHECK-LABEL: @insert_s -#[no_mangle] -pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> { - // CHECK: insertelement <4 x float> %{{v|0|1}}, float %j, i32 %i - simd_insert(v, i, j) -} diff --git a/tests/ui/simd/array-trait.rs b/tests/ui/simd/array-trait.rs index bf1e219460f4b..55fec7a3948bf 100644 --- a/tests/ui/simd/array-trait.rs +++ b/tests/ui/simd/array-trait.rs @@ -33,12 +33,7 @@ extern "platform-intrinsic" { pub fn main() { let mut t = T::([0; 4]); unsafe { - for i in 0_i32..4 { - t = simd_insert(t, i as u32, i); - } - for i in 0_i32..4 { - assert_eq!(i, simd_extract(t, i as u32)); - //~^ ERROR: use of moved value: `t` - } + t = simd_insert(t, 3, 3); + assert_eq!(3, simd_extract(t, 3)); } } diff --git a/tests/ui/simd/array-trait.stderr b/tests/ui/simd/array-trait.stderr index bbaead569dfc4..16ff732396dd4 100644 --- a/tests/ui/simd/array-trait.stderr +++ b/tests/ui/simd/array-trait.stderr @@ -23,18 +23,6 @@ LL | pub struct T([S::Lane; S::SIZE]); = help: try adding a `where` bound using this expression: `where [(); S::SIZE]:` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0382]: use of moved value: `t` - --> $DIR/array-trait.rs:40:40 - | -LL | let mut t = T::([0; 4]); - | ----- move occurs because `t` has type `T`, which does not implement the `Copy` trait -... -LL | for i in 0_i32..4 { - | ----------------- inside of this loop -LL | assert_eq!(i, simd_extract(t, i as u32)); - | ^ value moved here, in previous iteration of loop - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0077, E0382. -For more information about an error, try `rustc --explain E0077`. +For more information about this error, try `rustc --explain E0077`. diff --git a/tests/ui/simd/array-type.rs b/tests/ui/simd/array-type.rs index c9f5ed0d03130..0864c3e7418d0 100644 --- a/tests/ui/simd/array-type.rs +++ b/tests/ui/simd/array-type.rs @@ -22,21 +22,13 @@ pub fn main() { let mut s = S([0; 4]); unsafe { - for i in 0_i32..4 { - s = simd_insert(s, i as u32, i); - } - for i in 0_i32..4 { - assert_eq!(i, simd_extract(s, i as u32)); - } + s = simd_insert(s, 3, 3); + assert_eq!(3, simd_extract(s, 3)); } let mut t = T::<4>([0; 4]); unsafe { - for i in 0_i32..4 { - t = simd_insert(t, i as u32, i); - } - for i in 0_i32..4 { - assert_eq!(i, simd_extract(t, i as u32)); - } + t = simd_insert(t, 3, 3); + assert_eq!(3, simd_extract(t, 3)); } }