diff --git a/compiler/rustc_error_codes/src/error_codes/E0799.md b/compiler/rustc_error_codes/src/error_codes/E0799.md new file mode 100644 index 0000000000000..8408336fe7c0b --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0799.md @@ -0,0 +1,9 @@ +A scalable SIMD type was used in a context where they cannot exist. Scalable +SIMD types exist in a place that is somewhere between `Sized` and `Unsized` +therefore have restrictions on the uses. A scalable SIMD type can't exist in any +of the following: + +* Struct +* Enum variant +* Union +* Compound type. diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 57aed6d283353..837a9de018666 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -535,6 +535,7 @@ E0795: 0795, E0796: 0796, E0797: 0797, E0798: 0798, +E0799: 0799, ); ) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4fd7c870fc730..a4aca974517f3 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1114,10 +1114,9 @@ fn check_type_defn<'tcx>( }; // All fields (except for possibly the last) should be sized. let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy(); - let unsized_len = if all_sized { 0 } else { 1 }; - for (idx, field) in - variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate() - { + let unsized_len = + if all_sized { variant.fields.len() } else { variant.fields.len() - 1 }; + for (idx, field) in variant.fields.raw.iter().enumerate() { let last = idx == variant.fields.len() - 1; let field_id = field.did.expect_local(); let hir::FieldDef { ty: hir_ty, .. } = @@ -1127,28 +1126,45 @@ fn check_type_defn<'tcx>( None, tcx.type_of(field.did).instantiate_identity(), ); - wfcx.register_bound( - traits::ObligationCause::new( + if matches!(ty.kind(), ty::Adt(def, _) if def.repr().scalable()) { + struct_span_code_err!( + tcx.dcx(), hir_ty.span, - wfcx.body_def_id, - traits::FieldSized { - adt_kind: match &item.kind { - ItemKind::Struct(..) => AdtKind::Struct, - ItemKind::Union(..) => AdtKind::Union, - ItemKind::Enum(..) => AdtKind::Enum, - kind => span_bug!( - item.span, - "should be wfchecking an ADT, got {kind:?}" - ), + E0799, + "Scalable simd types cannot exist within {}", + match &item.kind { + ItemKind::Struct(..) => "a struct", + ItemKind::Union(..) => "a union", + ItemKind::Enum(..) => "enum variants", + kind => + span_bug!(item.span, "should be wfchecking an ADT, got {kind:?}"), + } + ) + .emit(); + } else if idx < unsized_len { + wfcx.register_bound( + traits::ObligationCause::new( + hir_ty.span, + wfcx.body_def_id, + traits::FieldSized { + adt_kind: match &item.kind { + ItemKind::Struct(..) => AdtKind::Struct, + ItemKind::Union(..) => AdtKind::Union, + ItemKind::Enum(..) => AdtKind::Enum, + kind => span_bug!( + item.span, + "should be wfchecking an ADT, got {kind:?}" + ), + }, + span: hir_ty.span, + last, }, - span: hir_ty.span, - last, - }, - ), - wfcx.param_env, - ty, - tcx.require_lang_item(LangItem::Sized, None), - ); + ), + wfcx.param_env, + ty, + tcx.require_lang_item(LangItem::Sized, None), + ); + } } // Explicit `enum` discriminant values must const-evaluate successfully. diff --git a/tests/ui/simd/scalable/disallow-array.rs b/tests/ui/simd/scalable/disallow-array.rs new file mode 100644 index 0000000000000..0520d3f58b742 --- /dev/null +++ b/tests/ui/simd/scalable/disallow-array.rs @@ -0,0 +1,10 @@ +#![feature(repr_simd, repr_scalable)] + +#[repr(simd, scalable(4))] +pub struct ScalableSimdFloat { + _ty: [f32] +} + +fn main() { + let x: [ScalableSimdFloat; 2]; //~ ERROR E0277 +} diff --git a/tests/ui/simd/scalable/disallow-array.stderr b/tests/ui/simd/scalable/disallow-array.stderr new file mode 100644 index 0000000000000..e8c92cb51651f --- /dev/null +++ b/tests/ui/simd/scalable/disallow-array.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `[f32]` cannot be known at compilation time + --> $DIR/disallow-array.rs:9:12 + | +LL | let x: [ScalableSimdFloat; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `ScalableSimdFloat`, the trait `Sized` is not implemented for `[f32]`, which is required by `ScalableSimdFloat: Sized` +note: required because it appears within the type `ScalableSimdFloat` + --> $DIR/disallow-array.rs:4:12 + | +LL | pub struct ScalableSimdFloat { + | ^^^^^^^^^^^^^^^^^ + = note: slice and array elements must have `Sized` type + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/simd/scalable/disallow-enum.rs b/tests/ui/simd/scalable/disallow-enum.rs new file mode 100644 index 0000000000000..627207b2e8acb --- /dev/null +++ b/tests/ui/simd/scalable/disallow-enum.rs @@ -0,0 +1,14 @@ +#![feature(repr_simd, repr_scalable)] + +#[repr(simd, scalable(4))] +pub struct ScalableSimdFloat { + _ty: [f32] +} + +pub enum Invalid { + Scalable(ScalableSimdFloat), //~ ERROR E0799 + Int(i32), +} + +fn main() { +} diff --git a/tests/ui/simd/scalable/disallow-enum.stderr b/tests/ui/simd/scalable/disallow-enum.stderr new file mode 100644 index 0000000000000..a2e71d94599ca --- /dev/null +++ b/tests/ui/simd/scalable/disallow-enum.stderr @@ -0,0 +1,9 @@ +error[E0799]: Scalable simd types cannot exist within enum variants + --> $DIR/disallow-enum.rs:9:14 + | +LL | Scalable(ScalableSimdFloat), + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0799`. diff --git a/tests/ui/simd/scalable/disallow-struct.rs b/tests/ui/simd/scalable/disallow-struct.rs new file mode 100644 index 0000000000000..c5e2f1c73e075 --- /dev/null +++ b/tests/ui/simd/scalable/disallow-struct.rs @@ -0,0 +1,17 @@ +#![feature(repr_simd, repr_scalable)] + +#[repr(simd, scalable(4))] +pub struct ScalableSimdFloat { + _ty: [f32] +} + +pub struct Invalid { + x: ScalableSimdFloat, //~ ERROR E0799 + last: i32, +} + +#[repr(transparent)] +struct Wrap(ScalableSimdFloat); //~ ERROR E0799 + +fn main() { +} diff --git a/tests/ui/simd/scalable/disallow-struct.stderr b/tests/ui/simd/scalable/disallow-struct.stderr new file mode 100644 index 0000000000000..ea223c76b6b9c --- /dev/null +++ b/tests/ui/simd/scalable/disallow-struct.stderr @@ -0,0 +1,15 @@ +error[E0799]: Scalable simd types cannot exist within a struct + --> $DIR/disallow-struct.rs:9:8 + | +LL | x: ScalableSimdFloat, + | ^^^^^^^^^^^^^^^^^ + +error[E0799]: Scalable simd types cannot exist within a struct + --> $DIR/disallow-struct.rs:14:13 + | +LL | struct Wrap(ScalableSimdFloat); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0799`. diff --git a/tests/ui/simd/scalable/disallow-union.rs b/tests/ui/simd/scalable/disallow-union.rs new file mode 100644 index 0000000000000..3506cb6b650b1 --- /dev/null +++ b/tests/ui/simd/scalable/disallow-union.rs @@ -0,0 +1,14 @@ +#![feature(repr_simd, repr_scalable)] + +#[repr(simd, scalable(4))] +pub struct ScalableSimdFloat { + _ty: [f32] +} + +pub union Invalid { + x: ScalableSimdFloat, //~ ERROR E0799 + other: i32, +} + +fn main() { +} diff --git a/tests/ui/simd/scalable/disallow-union.stderr b/tests/ui/simd/scalable/disallow-union.stderr new file mode 100644 index 0000000000000..b45b9c12ebd66 --- /dev/null +++ b/tests/ui/simd/scalable/disallow-union.stderr @@ -0,0 +1,9 @@ +error[E0799]: Scalable simd types cannot exist within a union + --> $DIR/disallow-union.rs:9:8 + | +LL | x: ScalableSimdFloat, + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0799`.