Skip to content

Commit

Permalink
Scalable SIMD tests for disallowing scalable types in types.
Browse files Browse the repository at this point in the history
Tests to ensure that scalable SIMD types can't exist in
struct, union, enum variants and compound types.

This also changes the well formed checking of types to improve the
error message when scalable SIMD types are included. The previous
implementation would also allow a scalable SIMD type as the last
element within a struct in some cases which we currently don't want to
allow.
  • Loading branch information
JamieCunliffe committed Apr 2, 2024
1 parent cf3864a commit 6321f69
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 24 deletions.
9 changes: 9 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0799.md
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions compiler/rustc_error_codes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ E0795: 0795,
E0796: 0796,
E0797: 0797,
E0798: 0798,
E0799: 0799,
);
)
}
Expand Down
64 changes: 40 additions & 24 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, .. } =
Expand All @@ -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.
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/simd/scalable/disallow-array.rs
Original file line number Diff line number Diff line change
@@ -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
}
17 changes: 17 additions & 0 deletions tests/ui/simd/scalable/disallow-array.stderr
Original file line number Diff line number Diff line change
@@ -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`.
14 changes: 14 additions & 0 deletions tests/ui/simd/scalable/disallow-enum.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
9 changes: 9 additions & 0 deletions tests/ui/simd/scalable/disallow-enum.stderr
Original file line number Diff line number Diff line change
@@ -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`.
17 changes: 17 additions & 0 deletions tests/ui/simd/scalable/disallow-struct.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
15 changes: 15 additions & 0 deletions tests/ui/simd/scalable/disallow-struct.stderr
Original file line number Diff line number Diff line change
@@ -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`.
14 changes: 14 additions & 0 deletions tests/ui/simd/scalable/disallow-union.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
9 changes: 9 additions & 0 deletions tests/ui/simd/scalable/disallow-union.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 6321f69

Please sign in to comment.