diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl index ae795ef2214b8..de2c3b63997ed 100644 --- a/compiler/rustc_ty_utils/messages.ftl +++ b/compiler/rustc_ty_utils/messages.ftl @@ -42,8 +42,6 @@ ty_utils_logical_op_not_supported = unsupported operation in generic constants, ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants -ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with more than one array field - ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index 5497d7d0bd2a0..8877bb45ceb22 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -82,12 +82,6 @@ pub(crate) struct ZeroLengthSimdType<'tcx> { pub ty: Ty<'tcx>, } -#[derive(Diagnostic)] -#[diag(ty_utils_multiple_array_fields_simd_type)] -pub(crate) struct MultipleArrayFieldsSimdType<'tcx> { - pub ty: Ty<'tcx>, -} - #[derive(Diagnostic)] #[diag(ty_utils_oversized_simd_type)] pub(crate) struct OversizedSimdType<'tcx> { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 1a82d17130755..852d3fc58d879 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -28,9 +28,7 @@ use rustc_span::{Symbol, sym}; use tracing::{debug, instrument, trace}; use {rustc_abi as abi, rustc_hir as hir}; -use crate::errors::{ - MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType, -}; +use crate::errors::{NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType}; mod invariant; @@ -450,71 +448,26 @@ fn layout_of_uncached<'tcx>( // SIMD vector types. ty::Adt(def, args) if def.repr().simd() => { - if !def.is_struct() { - // Should have yielded E0517 by now. - let guar = tcx - .dcx() - .delayed_bug("#[repr(simd)] was applied to an ADT that is not a struct"); - return Err(error(cx, LayoutError::ReferencesError(guar))); - } - - let fields = &def.non_enum_variant().fields; - - // Supported SIMD vectors are homogeneous ADTs with at least one field: + // Supported SIMD vectors are ADTs with a single array field: // - // * #[repr(simd)] struct S(T, T, T, T); - // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T } // * #[repr(simd)] struct S([T; 4]) // // where T is a primitive scalar (integer/float/pointer). - - // SIMD vectors with zero fields are not supported. - // (should be caught by typeck) - if fields.is_empty() { - tcx.dcx().emit_fatal(ZeroLengthSimdType { ty }) - } - - // Type of the first ADT field: - let f0_ty = fields[FieldIdx::ZERO].ty(tcx, args); - - // Heterogeneous SIMD vectors are not supported: - // (should be caught by typeck) - for fi in fields { - if fi.ty(tcx, args) != f0_ty { - let guar = tcx.dcx().delayed_bug( - "#[repr(simd)] was applied to an ADT with heterogeneous field type", - ); - return Err(error(cx, LayoutError::ReferencesError(guar))); - } - } - - // The element type and number of elements of the SIMD vector - // are obtained from: - // - // * the element type and length of the single array field, if - // the first field is of array type, or - // - // * the homogeneous field type and the number of fields. - let (e_ty, e_len, is_array) = if let ty::Array(e_ty, _) = f0_ty.kind() { - // First ADT field is an array: - - // SIMD vectors with multiple array fields are not supported: - // Can't be caught by typeck with a generic simd type. - if def.non_enum_variant().fields.len() != 1 { - tcx.dcx().emit_fatal(MultipleArrayFieldsSimdType { ty }); - } - - // Extract the number of elements from the layout of the array field: - let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else { - return Err(error(cx, LayoutError::Unknown(ty))); - }; - - (*e_ty, *count, true) - } else { - // First ADT field is not an array: - (f0_ty, def.non_enum_variant().fields.len() as _, false) + let Some(ty::Array(e_ty, e_len)) = def + .is_struct() + .then(|| &def.variant(FIRST_VARIANT).fields) + .filter(|fields| fields.len() == 1) + .map(|fields| *fields[FieldIdx::ZERO].ty(tcx, args).kind()) + else { + // Invalid SIMD types should have been caught by typeck by now. + let guar = tcx.dcx().delayed_bug("#[repr(simd)] was applied to an invalid ADT"); + return Err(error(cx, LayoutError::ReferencesError(guar))); }; + let e_len = extract_const_value(cx, ty, e_len)? + .try_to_target_usize(tcx) + .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; + // SIMD vectors of zero length are not supported. // Additionally, lengths are capped at 2^16 as a fixed maximum backends must // support. @@ -559,16 +512,12 @@ fn layout_of_uncached<'tcx>( }; let size = size.align_to(align.abi); - // Compute the placement of the vector fields: - let fields = if is_array { - FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() } - } else { - FieldsShape::Array { stride: e_ly.size, count: e_len } - }; - tcx.mk_layout(LayoutData { variants: Variants::Single { index: FIRST_VARIANT }, - fields, + fields: FieldsShape::Arbitrary { + offsets: [Size::ZERO].into(), + memory_index: [0].into(), + }, backend_repr: abi, largest_niche: e_ly.largest_niche, uninhabited: false, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index a4e49e0aa10ab..7af31dabe45b3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -133,40 +133,22 @@ fn layout_of_simd_ty( env: Arc, dl: &TargetDataLayout, ) -> Result, LayoutError> { - let fields = db.field_types(id.into()); - - // Supported SIMD vectors are homogeneous ADTs with at least one field: + // Supported SIMD vectors are homogeneous ADTs with exactly one array field: // - // * #[repr(simd)] struct S(T, T, T, T); - // * #[repr(simd)] struct S { it: T, y: T, z: T, w: T } // * #[repr(simd)] struct S([T; 4]) // // where T is a primitive scalar (integer/float/pointer). - - let f0_ty = match fields.iter().next() { - Some(it) => it.1.clone().substitute(Interner, subst), - None => return Err(LayoutError::InvalidSimdType), + let fields = db.field_types(id.into()); + let mut fields = fields.iter(); + let Some(TyKind::Array(e_ty, e_len)) = fields + .next() + .filter(|_| fields.next().is_none()) + .map(|f| f.1.clone().substitute(Interner, subst).kind(Interner).clone()) + else { + return Err(LayoutError::InvalidSimdType); }; - // The element type and number of elements of the SIMD vector - // are obtained from: - // - // * the element type and length of the single array field, if - // the first field is of array type, or - // - // * the homogeneous field type and the number of fields. - let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) { - // Extract the number of elements from the layout of the array field: - let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields - else { - return Err(LayoutError::Unknown); - }; - - (e_ty.clone(), count, true) - } else { - // First ADT field is not an array: - (f0_ty, fields.iter().count() as u64, false) - }; + let e_len = try_const_usize(db, &e_len).ok_or(LayoutError::HasErrorConst)? as u64; // Compute the ABI of the element type: let e_ly = db.layout_of_ty(e_ty, env)?; @@ -182,16 +164,9 @@ fn layout_of_simd_ty( let align = dl.llvmlike_vector_align(size); let size = size.align_to(align.abi); - // Compute the placement of the vector fields: - let fields = if is_array { - FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() } - } else { - FieldsShape::Array { stride: e_ly.size, count: e_len } - }; - Ok(Arc::new(Layout { variants: Variants::Single { index: struct_variant_idx() }, - fields, + fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }, backend_repr: BackendRepr::SimdVector { element: e_abi, count: e_len }, largest_niche: e_ly.largest_niche, uninhabited: false,