From ba9262936ec0f85a53a5407fa903931e2b8031e4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 9 Jul 2025 16:25:29 +0000 Subject: [PATCH] hir/trait_sel: prohibit scalable vectors in types Extend well-formedness checking and HIR analysis to prohibit the use of scalable vectors in structs, enums, unions, tuples and arrays. LLVM does not support scalable vectors being members of other types, so these restrictions are necessary. Co-authored-by: Jamie Cunliffe --- compiler/rustc_ast_passes/messages.ftl | 2 + .../rustc_ast_passes/src/ast_validation.rs | 8 ++ compiler/rustc_ast_passes/src/errors.rs | 7 + .../rustc_hir_analysis/src/check/check.rs | 100 +++++++++++++- .../rustc_hir_analysis/src/check/wfcheck.rs | 18 ++- .../rustc_trait_selection/src/traits/wf.rs | 18 ++- .../illformed-element-type.rs | 93 +++++++++++++ .../illformed-element-type.stderr | 122 +++++++++++++++++ .../illformed-tuples-of-scalable-vectors.rs | 36 +++++ ...llformed-tuples-of-scalable-vectors.stderr | 38 ++++++ .../illformed-within-types.rs | 23 ++++ .../illformed-within-types.stderr | 32 +++++ tests/ui/scalable-vectors/illformed.rs | 59 +++++++++ tests/ui/scalable-vectors/illformed.stderr | 125 ++++++++++++++++++ tests/ui/scalable-vectors/invalid.rs | 1 + tests/ui/scalable-vectors/invalid.stderr | 8 +- .../ui/scalable-vectors/wellformed-arrays.rs | 10 ++ tests/ui/scalable-vectors/wellformed.rs | 48 +++++++ 18 files changed, 742 insertions(+), 6 deletions(-) create mode 100644 tests/ui/scalable-vectors/illformed-element-type.rs create mode 100644 tests/ui/scalable-vectors/illformed-element-type.stderr create mode 100644 tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.rs create mode 100644 tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.stderr create mode 100644 tests/ui/scalable-vectors/illformed-within-types.rs create mode 100644 tests/ui/scalable-vectors/illformed-within-types.stderr create mode 100644 tests/ui/scalable-vectors/illformed.rs create mode 100644 tests/ui/scalable-vectors/illformed.stderr create mode 100644 tests/ui/scalable-vectors/wellformed-arrays.rs create mode 100644 tests/ui/scalable-vectors/wellformed.rs diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index f1f734b855c1..b9117c83ae2f 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -270,6 +270,8 @@ ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc} +ast_passes_scalable_vector_not_tuple_struct = scalable vectors must be tuple structs + ast_passes_static_without_body = free static item without body .suggestion = provide a definition for the static diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0d34ba6c2ca8..a083ca7d133e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1319,6 +1319,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Struct(ident, generics, vdata) => { self.with_tilde_const(Some(TildeConstReason::Struct { span: item.span }), |this| { + // Scalable vectors can only be tuple structs + let is_scalable_vector = + item.attrs.iter().any(|attr| attr.has_name(sym::rustc_scalable_vector)); + if is_scalable_vector && !matches!(vdata, VariantData::Tuple(..)) { + this.dcx() + .emit_err(errors::ScalableVectorNotTupleStruct { span: item.span }); + } + match vdata { VariantData::Struct { fields, .. } => { this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index bf9309614fe2..22adaae8c6f2 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -990,3 +990,10 @@ pub(crate) struct AbiX86Interrupt { pub spans: Vec, pub param_count: usize, } + +#[derive(Diagnostic)] +#[diag(ast_passes_scalable_vector_not_tuple_struct)] +pub(crate) struct ScalableVectorNotTupleStruct { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index beba0165549e..a81df02f023f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,7 +1,7 @@ use std::cell::LazyCell; use std::ops::ControlFlow; -use rustc_abi::{ExternAbi, FieldIdx}; +use rustc_abi::{ExternAbi, FieldIdx, ScalableElt}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{EmissionGuarantee, MultiSpan}; @@ -92,7 +92,9 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { let span = tcx.def_span(def_id); def.destructor(tcx); // force the destructor to be evaluated - if def.repr().simd() { + if let Some(scalable) = def.repr().scalable { + check_scalable_vector(tcx, span, def_id, scalable); + } else if def.repr().simd() { check_simd(tcx, span, def_id); } @@ -1426,6 +1428,100 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { } } +#[tracing::instrument(skip(tcx), level = "debug")] +fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalable: ScalableElt) { + let ty = tcx.type_of(def_id).instantiate_identity(); + let ty::Adt(def, args) = ty.kind() else { return }; + if !def.is_struct() { + tcx.dcx().delayed_bug("`rustc_scalable_vector` applied to non-struct"); + return; + } + + let fields = &def.non_enum_variant().fields; + match scalable { + ScalableElt::ElementCount(..) if fields.is_empty() => { + let mut err = + tcx.dcx().struct_span_err(span, "scalable vectors must have a single field"); + err.help("scalable vector types' only field must be a primitive scalar type"); + err.emit(); + return; + } + ScalableElt::ElementCount(..) if fields.len() >= 2 => { + tcx.dcx().struct_span_err(span, "scalable vectors cannot have multiple fields").emit(); + return; + } + ScalableElt::Container if fields.is_empty() => { + let mut err = + tcx.dcx().struct_span_err(span, "scalable vectors must have a single field"); + err.help("tuples of scalable vectors can only contain multiple of the same scalable vector type"); + err.emit(); + return; + } + _ => {} + } + + match scalable { + ScalableElt::ElementCount(..) => { + let element_ty = &fields[FieldIdx::ZERO].ty(tcx, args); + + // Check that `element_ty` only uses types valid in the lanes of a scalable vector + // register: scalar types which directly match a "machine" type - integers, floats and + // bools + match element_ty.kind() { + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool => (), + _ => { + let mut err = tcx.dcx().struct_span_err( + span, + "element type of a scalable vector must be a primitive scalar", + ); + err.help("only `u*`, `i*`, `f*` and `bool` types are accepted"); + err.emit(); + } + } + } + ScalableElt::Container => { + let mut prev_field_ty = None; + for field in fields.iter() { + let element_ty = field.ty(tcx, args); + if let ty::Adt(def, _) = element_ty.kind() + && def.repr().scalable() + { + match def + .repr() + .scalable + .expect("`repr().scalable.is_some()` != `repr().scalable()`") + { + ScalableElt::ElementCount(_) => { /* expected field */ } + ScalableElt::Container => { + tcx.dcx().span_err( + tcx.def_span(field.did), + "scalable vector structs cannot contain other scalable vector structs", + ); + break; + } + } + } else { + tcx.dcx().span_err( + tcx.def_span(field.did), + "scalable vector structs can only have scalable vector fields", + ); + break; + } + + if let Some(prev_ty) = prev_field_ty.replace(element_ty) + && prev_ty != element_ty + { + tcx.dcx().span_err( + tcx.def_span(field.did), + "all fields in a scalable vector struct must be the same type", + ); + break; + } + } + } + } +} + pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { let repr = def.repr(); if repr.packed() { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5ed0e0018f8d..16f5222f621c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2,7 +2,7 @@ use std::cell::LazyCell; use std::ops::{ControlFlow, Deref}; use hir::intravisit::{self, Visitor}; -use rustc_abi::ExternAbi; +use rustc_abi::{ExternAbi, ScalableElt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; @@ -1038,7 +1038,21 @@ fn check_type_defn<'tcx>( hir_ty.span, Some(WellFormedLoc::Ty(field_id)), ty.into(), - ) + ); + + if matches!(ty.kind(), ty::Adt(def, _) if def.repr().scalable()) + && !matches!(adt_def.repr().scalable, Some(ScalableElt::Container)) + { + // Scalable vectors can only be fields of structs if the type has a + // `rustc_scalable_vector` attribute w/out specifying an element count + tcx.dcx().span_err( + hir_ty.span, + format!( + "scalable vectors cannot be fields of a {}", + adt_def.variant_descr() + ), + ); + } } // For DST, or when drop needs to copy things around, all diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index db7bd635f32e..394095508393 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -771,9 +771,25 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::Tuple(tys) => { - if let Some((_last, rest)) = tys.split_last() { + if let Some((last, rest)) = tys.split_last() { for &elem in rest { self.require_sized(elem, ObligationCauseCode::TupleElem); + if elem.is_scalable_vector() && !self.span.is_dummy() { + self.tcx() + .dcx() + .struct_span_err( + self.span, + "scalable vectors cannot be tuple fields", + ) + .emit(); + } + } + + if last.is_scalable_vector() && !self.span.is_dummy() { + self.tcx() + .dcx() + .struct_span_err(self.span, "scalable vectors cannot be tuple fields") + .emit(); } } } diff --git a/tests/ui/scalable-vectors/illformed-element-type.rs b/tests/ui/scalable-vectors/illformed-element-type.rs new file mode 100644 index 000000000000..469ca006f5e9 --- /dev/null +++ b/tests/ui/scalable-vectors/illformed-element-type.rs @@ -0,0 +1,93 @@ +//@ compile-flags: --crate-type=lib +#![allow(internal_features)] +#![feature(extern_types)] +#![feature(never_type)] +#![feature(rustc_attrs)] + +struct Foo; +enum Bar {} +union Baz { x: u16 } +extern "C" { + type Qux; +} + +#[rustc_scalable_vector(4)] +struct TyChar(char); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(2)] +struct TyConstPtr(*const u8); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(2)] +struct TyMutPtr(*mut u8); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyStruct(Foo); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyEnum(Bar); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyUnion(Baz); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyForeign(Qux); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyArray([u32; 4]); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TySlice([u32]); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyRef<'a>(&'a u32); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyFnPtr(fn(u32) -> u32); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyDyn(dyn std::io::Write); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyNever(!); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +#[rustc_scalable_vector(4)] +struct TyTuple((u32, u32)); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +type ValidAlias = u32; +type InvalidAlias = String; + +#[rustc_scalable_vector(4)] +struct TyValidAlias(ValidAlias); + +#[rustc_scalable_vector(4)] +struct TyInvalidAlias(InvalidAlias); +//~^ ERROR: element type of a scalable vector must be a primitive scalar + +trait Tr { + type Valid; + type Invalid; +} + +impl Tr for () { + type Valid = u32; + type Invalid = String; +} + +struct TyValidProjection(<() as Tr>::Valid); + +struct TyInvalidProjection(<() as Tr>::Invalid); +// FIXME: element type of a scalable vector must be a primitive scalar diff --git a/tests/ui/scalable-vectors/illformed-element-type.stderr b/tests/ui/scalable-vectors/illformed-element-type.stderr new file mode 100644 index 000000000000..f8ca8b76215f --- /dev/null +++ b/tests/ui/scalable-vectors/illformed-element-type.stderr @@ -0,0 +1,122 @@ +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:15:1 + | +LL | struct TyChar(char); + | ^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:19:1 + | +LL | struct TyConstPtr(*const u8); + | ^^^^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:23:1 + | +LL | struct TyMutPtr(*mut u8); + | ^^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:27:1 + | +LL | struct TyStruct(Foo); + | ^^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:31:1 + | +LL | struct TyEnum(Bar); + | ^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:35:1 + | +LL | struct TyUnion(Baz); + | ^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:39:1 + | +LL | struct TyForeign(Qux); + | ^^^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:43:1 + | +LL | struct TyArray([u32; 4]); + | ^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:47:1 + | +LL | struct TySlice([u32]); + | ^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:51:1 + | +LL | struct TyRef<'a>(&'a u32); + | ^^^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:55:1 + | +LL | struct TyFnPtr(fn(u32) -> u32); + | ^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:59:1 + | +LL | struct TyDyn(dyn std::io::Write); + | ^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:63:1 + | +LL | struct TyNever(!); + | ^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:67:1 + | +LL | struct TyTuple((u32, u32)); + | ^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: element type of a scalable vector must be a primitive scalar + --> $DIR/illformed-element-type.rs:77:1 + | +LL | struct TyInvalidAlias(InvalidAlias); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: only `u*`, `i*`, `f*` and `bool` types are accepted + +error: aborting due to 15 previous errors + diff --git a/tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.rs b/tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.rs new file mode 100644 index 000000000000..4f89a8f9055e --- /dev/null +++ b/tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.rs @@ -0,0 +1,36 @@ +//@ compile-flags: --crate-type=lib +#![allow(internal_features)] +#![feature(rustc_attrs)] + +#[rustc_scalable_vector(2)] +struct ValidI64(i64); + +#[rustc_scalable_vector(4)] +struct ValidI32(i32); + +#[rustc_scalable_vector] +struct ValidTuple(ValidI32, ValidI32, ValidI32); + +#[rustc_scalable_vector] +struct Struct { x: ValidI64, y: ValidI64 } +//~^ ERROR: scalable vectors must be tuple structs + +#[rustc_scalable_vector] +struct DifferentVectorTypes(ValidI64, ValidI32); +//~^ ERROR: all fields in a scalable vector struct must be the same type + +#[rustc_scalable_vector] +struct NonVectorTypes(u32, u64); +//~^ ERROR: scalable vector structs can only have scalable vector fields + +#[rustc_scalable_vector] +struct DifferentNonVectorTypes(u32, u64); +//~^ ERROR: scalable vector structs can only have scalable vector fields + +#[rustc_scalable_vector] +struct SomeVectorTypes(ValidI64, u64); +//~^ ERROR: scalable vector structs can only have scalable vector fields + +#[rustc_scalable_vector] +struct NestedTuple(ValidTuple, ValidTuple); +//~^ ERROR: scalable vector structs cannot contain other scalable vector structs diff --git a/tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.stderr b/tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.stderr new file mode 100644 index 000000000000..f5fd963204a2 --- /dev/null +++ b/tests/ui/scalable-vectors/illformed-tuples-of-scalable-vectors.stderr @@ -0,0 +1,38 @@ +error: scalable vectors must be tuple structs + --> $DIR/illformed-tuples-of-scalable-vectors.rs:15:1 + | +LL | struct Struct { x: ValidI64, y: ValidI64 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: all fields in a scalable vector struct must be the same type + --> $DIR/illformed-tuples-of-scalable-vectors.rs:19:39 + | +LL | struct DifferentVectorTypes(ValidI64, ValidI32); + | ^^^^^^^^ + +error: scalable vector structs can only have scalable vector fields + --> $DIR/illformed-tuples-of-scalable-vectors.rs:23:23 + | +LL | struct NonVectorTypes(u32, u64); + | ^^^ + +error: scalable vector structs can only have scalable vector fields + --> $DIR/illformed-tuples-of-scalable-vectors.rs:27:32 + | +LL | struct DifferentNonVectorTypes(u32, u64); + | ^^^ + +error: scalable vector structs can only have scalable vector fields + --> $DIR/illformed-tuples-of-scalable-vectors.rs:31:34 + | +LL | struct SomeVectorTypes(ValidI64, u64); + | ^^^ + +error: scalable vector structs cannot contain other scalable vector structs + --> $DIR/illformed-tuples-of-scalable-vectors.rs:35:20 + | +LL | struct NestedTuple(ValidTuple, ValidTuple); + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/scalable-vectors/illformed-within-types.rs b/tests/ui/scalable-vectors/illformed-within-types.rs new file mode 100644 index 000000000000..81d960e4d4e1 --- /dev/null +++ b/tests/ui/scalable-vectors/illformed-within-types.rs @@ -0,0 +1,23 @@ +//@ compile-flags: --crate-type=lib +#![allow(internal_features)] +#![feature(rustc_attrs)] + +#[rustc_scalable_vector(2)] +struct ValidI64(i64); + +struct Struct { + x: ValidI64, +//~^ ERROR: scalable vectors cannot be fields of a struct + in_tuple: (ValidI64,), +//~^ ERROR: scalable vectors cannot be tuple fields +} + +struct TupleStruct(ValidI64); +//~^ ERROR: scalable vectors cannot be fields of a struct + +enum Enum { + StructVariant { _ty: ValidI64 }, +//~^ ERROR: scalable vectors cannot be fields of a variant + TupleVariant(ValidI64), +//~^ ERROR: scalable vectors cannot be fields of a variant +} diff --git a/tests/ui/scalable-vectors/illformed-within-types.stderr b/tests/ui/scalable-vectors/illformed-within-types.stderr new file mode 100644 index 000000000000..e76ef26f2aa4 --- /dev/null +++ b/tests/ui/scalable-vectors/illformed-within-types.stderr @@ -0,0 +1,32 @@ +error: scalable vectors cannot be fields of a struct + --> $DIR/illformed-within-types.rs:9:8 + | +LL | x: ValidI64, + | ^^^^^^^^ + +error: scalable vectors cannot be tuple fields + --> $DIR/illformed-within-types.rs:11:15 + | +LL | in_tuple: (ValidI64,), + | ^^^^^^^^^^^ + +error: scalable vectors cannot be fields of a struct + --> $DIR/illformed-within-types.rs:15:20 + | +LL | struct TupleStruct(ValidI64); + | ^^^^^^^^ + +error: scalable vectors cannot be fields of a variant + --> $DIR/illformed-within-types.rs:19:26 + | +LL | StructVariant { _ty: ValidI64 }, + | ^^^^^^^^ + +error: scalable vectors cannot be fields of a variant + --> $DIR/illformed-within-types.rs:21:18 + | +LL | TupleVariant(ValidI64), + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/scalable-vectors/illformed.rs b/tests/ui/scalable-vectors/illformed.rs new file mode 100644 index 000000000000..de135413a9f2 --- /dev/null +++ b/tests/ui/scalable-vectors/illformed.rs @@ -0,0 +1,59 @@ +//@ compile-flags: --crate-type=lib +#![allow(internal_features)] +#![feature(rustc_attrs)] + +#[rustc_scalable_vector(4)] +struct NoFieldsStructWithElementCount {} +//~^ ERROR: scalable vectors must have a single field +//~^^ ERROR: scalable vectors must be tuple structs + +#[rustc_scalable_vector(4)] +struct NoFieldsTupleWithElementCount(); +//~^ ERROR: scalable vectors must have a single field + +#[rustc_scalable_vector(4)] +struct NoFieldsUnitWithElementCount; +//~^ ERROR: scalable vectors must have a single field +//~^^ ERROR: scalable vectors must be tuple structs + +#[rustc_scalable_vector] +struct NoFieldsStructWithoutElementCount {} +//~^ ERROR: scalable vectors must have a single field +//~^^ ERROR: scalable vectors must be tuple structs + +#[rustc_scalable_vector] +struct NoFieldsTupleWithoutElementCount(); +//~^ ERROR: scalable vectors must have a single field + +#[rustc_scalable_vector] +struct NoFieldsUnitWithoutElementCount; +//~^ ERROR: scalable vectors must have a single field +//~^^ ERROR: scalable vectors must be tuple structs + +#[rustc_scalable_vector(4)] +struct MultipleFieldsStructWithElementCount { +//~^ ERROR: scalable vectors cannot have multiple fields +//~^^ ERROR: scalable vectors must be tuple structs + _ty: f32, + other: u32, +} + +#[rustc_scalable_vector(4)] +struct MultipleFieldsTupleWithElementCount(f32, u32); +//~^ ERROR: scalable vectors cannot have multiple fields + +#[rustc_scalable_vector] +struct MultipleFieldsStructWithoutElementCount { +//~^ ERROR: scalable vectors must be tuple structs + _ty: f32, +//~^ ERROR: scalable vector structs can only have scalable vector fields + other: u32, +} + +#[rustc_scalable_vector] +struct MultipleFieldsTupleWithoutElementCount(f32, u32); +//~^ ERROR: scalable vector structs can only have scalable vector fields + +#[rustc_scalable_vector(2)] +struct SingleFieldStruct { _ty: f64 } +//~^ ERROR: scalable vectors must be tuple structs diff --git a/tests/ui/scalable-vectors/illformed.stderr b/tests/ui/scalable-vectors/illformed.stderr new file mode 100644 index 000000000000..bdf519c91058 --- /dev/null +++ b/tests/ui/scalable-vectors/illformed.stderr @@ -0,0 +1,125 @@ +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:6:1 + | +LL | struct NoFieldsStructWithElementCount {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:15:1 + | +LL | struct NoFieldsUnitWithElementCount; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:20:1 + | +LL | struct NoFieldsStructWithoutElementCount {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:29:1 + | +LL | struct NoFieldsUnitWithoutElementCount; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:34:1 + | +LL | / struct MultipleFieldsStructWithElementCount { +LL | | +LL | | +LL | | _ty: f32, +LL | | other: u32, +LL | | } + | |_^ + +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:46:1 + | +LL | / struct MultipleFieldsStructWithoutElementCount { +LL | | +LL | | _ty: f32, +... | +LL | | } + | |_^ + +error: scalable vectors must be tuple structs + --> $DIR/illformed.rs:58:1 + | +LL | struct SingleFieldStruct { _ty: f64 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vectors must have a single field + --> $DIR/illformed.rs:6:1 + | +LL | struct NoFieldsStructWithElementCount {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: scalable vector types' only field must be a primitive scalar type + +error: scalable vectors must have a single field + --> $DIR/illformed.rs:11:1 + | +LL | struct NoFieldsTupleWithElementCount(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: scalable vector types' only field must be a primitive scalar type + +error: scalable vectors must have a single field + --> $DIR/illformed.rs:15:1 + | +LL | struct NoFieldsUnitWithElementCount; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: scalable vector types' only field must be a primitive scalar type + +error: scalable vectors must have a single field + --> $DIR/illformed.rs:20:1 + | +LL | struct NoFieldsStructWithoutElementCount {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: tuples of scalable vectors can only contain multiple of the same scalable vector type + +error: scalable vectors must have a single field + --> $DIR/illformed.rs:25:1 + | +LL | struct NoFieldsTupleWithoutElementCount(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: tuples of scalable vectors can only contain multiple of the same scalable vector type + +error: scalable vectors must have a single field + --> $DIR/illformed.rs:29:1 + | +LL | struct NoFieldsUnitWithoutElementCount; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: tuples of scalable vectors can only contain multiple of the same scalable vector type + +error: scalable vectors cannot have multiple fields + --> $DIR/illformed.rs:34:1 + | +LL | struct MultipleFieldsStructWithElementCount { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vectors cannot have multiple fields + --> $DIR/illformed.rs:42:1 + | +LL | struct MultipleFieldsTupleWithElementCount(f32, u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: scalable vector structs can only have scalable vector fields + --> $DIR/illformed.rs:48:5 + | +LL | _ty: f32, + | ^^^^^^^^ + +error: scalable vector structs can only have scalable vector fields + --> $DIR/illformed.rs:54:47 + | +LL | struct MultipleFieldsTupleWithoutElementCount(f32, u32); + | ^^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/scalable-vectors/invalid.rs b/tests/ui/scalable-vectors/invalid.rs index fde4911b2c8b..beb3ad66b78b 100644 --- a/tests/ui/scalable-vectors/invalid.rs +++ b/tests/ui/scalable-vectors/invalid.rs @@ -160,3 +160,4 @@ struct Okay(f32); #[rustc_scalable_vector] struct OkayNoArg(f32); +//~^ ERROR: scalable vector structs can only have scalable vector fields diff --git a/tests/ui/scalable-vectors/invalid.stderr b/tests/ui/scalable-vectors/invalid.stderr index 832bbe838dc4..43be84a8b005 100644 --- a/tests/ui/scalable-vectors/invalid.stderr +++ b/tests/ui/scalable-vectors/invalid.stderr @@ -327,7 +327,13 @@ LL | #[rustc_scalable_vector(65536)] | = note: the value may not exceed `u16::MAX` -error: aborting due to 38 previous errors +error: scalable vector structs can only have scalable vector fields + --> $DIR/invalid.rs:162:18 + | +LL | struct OkayNoArg(f32); + | ^^^ + +error: aborting due to 39 previous errors Some errors have detailed explanations: E0539, E0805. For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/scalable-vectors/wellformed-arrays.rs b/tests/ui/scalable-vectors/wellformed-arrays.rs new file mode 100644 index 000000000000..b8f0bf291eea --- /dev/null +++ b/tests/ui/scalable-vectors/wellformed-arrays.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +#![feature(rustc_attrs)] + +#[rustc_scalable_vector(16)] +struct ScalableU8(u8); + +fn main() { + let x: [ScalableU8; 4] = todo!(); +} diff --git a/tests/ui/scalable-vectors/wellformed.rs b/tests/ui/scalable-vectors/wellformed.rs new file mode 100644 index 000000000000..cb6a22d6c433 --- /dev/null +++ b/tests/ui/scalable-vectors/wellformed.rs @@ -0,0 +1,48 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +#![feature(rustc_attrs)] + +#[rustc_scalable_vector(16)] +struct ScalableU8(u8); + +#[rustc_scalable_vector(8)] +struct ScalableU16(u16); + +#[rustc_scalable_vector(4)] +struct ScalableU32(u32); + +#[rustc_scalable_vector(2)] +struct ScalableU64(u64); + +#[rustc_scalable_vector(1)] +struct ScalableU128(u128); + +#[rustc_scalable_vector(16)] +struct ScalableI8(i8); + +#[rustc_scalable_vector(8)] +struct ScalableI16(i16); + +#[rustc_scalable_vector(4)] +struct ScalableI32(i32); + +#[rustc_scalable_vector(2)] +struct ScalableI64(i64); + +#[rustc_scalable_vector(1)] +struct ScalableI128(i128); + +#[rustc_scalable_vector(8)] +struct ScalableF16(f32); + +#[rustc_scalable_vector(4)] +struct ScalableF32(f32); + +#[rustc_scalable_vector(2)] +struct ScalableF64(f64); + +#[rustc_scalable_vector(16)] +struct ScalableBool(bool); + +#[rustc_scalable_vector] +struct ScalableTuple(ScalableU8, ScalableU8, ScalableU8);