diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3d30bee47e44..531af34ee3b7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1349,7 +1349,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } self.check_rvalue(body, rv, location); - if !self.unsized_feature_enabled() { + if !(self.unsized_feature_enabled() || place_ty.is_scalable_simd()) { let trait_ref = ty::TraitRef::from_lang_item( tcx, LangItem::Sized, @@ -1857,7 +1857,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if !self.unsized_feature_enabled() { let span = local_decl.source_info.span; let ty = local_decl.ty; - self.ensure_place_sized(ty, span); + if !ty.is_scalable_simd() { + self.ensure_place_sized(ty, span); + } } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 4767c7f2b42c..f13d5daa54c3 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -620,8 +620,22 @@ declare_features! ( /// Allows unnamed fields of struct and union type (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows unsized fn parameters. + /// + /// Note: `repr_scalable` depends on this feature. Rather than forcing the developer to also + /// enable this feature to use scalable SIMD, we have done a check along side this feature to + /// check if the type is a scalable SIMD type. If this feature becomes stable, those checks + /// should be safe to remove so we can just use this feature. The check has been done specific + /// to the type rather than enabling this feature on their behalf to avoid enabling more unsized + /// than is actually required for what they are using. (unstable, unsized_fn_params, "1.49.0", Some(48055)), /// Allows unsized rvalues at arguments and parameters. + /// + /// Note: `repr_scalable` depends on this feature. Rather than forcing the developer to also + /// enable this feature to use scalable SIMD, we have done a check along side this feature to + /// check if the type is a scalable SIMD type. If this feature becomes stable, those checks + /// should be safe to remove so we can just use this feature. The check has been done specific + /// to the type rather than enabling this feature on their behalf to avoid enabling more unsized + /// than is actually required for what they are using. (incomplete, unsized_locals, "1.30.0", Some(48055)), /// Allows unsized tuple coercion. (unstable, unsized_tuple_coercion, "1.20.0", Some(42877)), diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b3bd6b8f25ee..968b52e3ee09 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -83,7 +83,7 @@ pub(super) fn check_fn<'a, 'tcx>( } // Check that argument is Sized. - if !params_can_be_unsized { + if !(params_can_be_unsized || param_ty.is_scalable_simd()) { fcx.require_type_is_sized( param_ty, param.pat.span, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 0225d20c33cc..8c355d76fd78 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -575,6 +575,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::FnCall, fn_sig.input(i), ); + + if input.is_scalable_simd() { + continue; + } + self.require_type_is_sized_deferred( input, span, diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index be5cd6e9d487..a796fd993ab1 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -144,7 +144,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { let var_ty = self.assign(p.span, p.hir_id, None); if let Some((ty_span, hir_id)) = self.outermost_fn_param_pat { - if !self.fcx.tcx.features().unsized_fn_params { + if !(self.fcx.tcx.features().unsized_fn_params + || self.fcx.tcx.features().repr_scalable) + { self.fcx.require_type_is_sized( var_ty, p.span, @@ -162,7 +164,9 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { ); } } else { - if !self.fcx.tcx.features().unsized_locals { + if !(self.fcx.tcx.features().unsized_locals + || self.fcx.tcx.features().repr_scalable) + { self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id)); } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 62ee210b8df0..1b8e7cdd5d0c 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -212,7 +212,6 @@ fn typeck_with_fallback<'tcx>( for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { let ty = fcx.normalize(span, ty); - // ScalableSIMD: Justify this. if !ty.is_scalable_simd() { fcx.require_type_is_sized(ty, span, code); } diff --git a/tests/ui/simd/scalable/disallow-capture-closure.rs b/tests/ui/simd/scalable/disallow-capture-closure.rs new file mode 100644 index 000000000000..cd9b026ef364 --- /dev/null +++ b/tests/ui/simd/scalable/disallow-capture-closure.rs @@ -0,0 +1,47 @@ +#![allow(incomplete_features, internal_features, improper_ctypes)] +#![feature( + repr_simd, + repr_scalable, + simd_ffi, + unsized_locals, + unsized_fn_params, + link_llvm_intrinsics +)] + +#[repr(simd, scalable(4))] +#[allow(non_camel_case_types)] +pub struct svint32_t { + _ty: [i32], +} + +#[inline(never)] +#[target_feature(enable = "sve")] +pub unsafe fn svdup_n_s32(op: i32) -> svint32_t { + extern "C" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.dup.x.nxv4i32")] + fn _svdup_n_s32(op: i32) -> svint32_t; + } + unsafe { _svdup_n_s32(op) } +} + +#[inline] +#[target_feature(enable = "sve,sve2")] +pub unsafe fn svxar_n_s32(op1: svint32_t, op2: svint32_t) -> svint32_t { + extern "C" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.xar.nxv4i32")] + fn _svxar_n_s32(op1: svint32_t, op2: svint32_t, imm3: i32) -> svint32_t; + } + unsafe { _svxar_n_s32(op1, op2, IMM3) } +} + +#[inline(never)] +fn run(f: impl Fn() -> ()) { + f(); +} + +fn main() { + let a = svdup_n_s32(42); + run(move || { + svxar_n_s32::<2>(a, a); //~ ERROR E0277 + }); +} diff --git a/tests/ui/simd/scalable/disallow-capture-closure.stderr b/tests/ui/simd/scalable/disallow-capture-closure.stderr new file mode 100644 index 000000000000..65c33d0e7b90 --- /dev/null +++ b/tests/ui/simd/scalable/disallow-capture-closure.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/disallow-capture-closure.rs:45:26 + | +LL | run(move || { + | -- this closure captures all values by move +LL | svxar_n_s32::<2>(a, a); + | ^ doesn't have a size known at compile-time + | + = help: within `svint32_t`, the trait `Sized` is not implemented for `[i32]`, which is required by `svint32_t: Sized` +note: required because it appears within the type `svint32_t` + --> $DIR/disallow-capture-closure.rs:13:12 + | +LL | pub struct svint32_t { + | ^^^^^^^^^ + = note: all values captured by value by a closure must have a statically known size + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.