Skip to content

Commit 6321f69

Browse files
committed
Scalable SIMD tests for disallowing scalable types in types.
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.
1 parent cf3864a commit 6321f69

File tree

11 files changed

+155
-24
lines changed

11 files changed

+155
-24
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
A scalable SIMD type was used in a context where they cannot exist. Scalable
2+
SIMD types exist in a place that is somewhere between `Sized` and `Unsized`
3+
therefore have restrictions on the uses. A scalable SIMD type can't exist in any
4+
of the following:
5+
6+
* Struct
7+
* Enum variant
8+
* Union
9+
* Compound type.

compiler/rustc_error_codes/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ E0795: 0795,
535535
E0796: 0796,
536536
E0797: 0797,
537537
E0798: 0798,
538+
E0799: 0799,
538539
);
539540
)
540541
}

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,10 +1114,9 @@ fn check_type_defn<'tcx>(
11141114
};
11151115
// All fields (except for possibly the last) should be sized.
11161116
let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
1117-
let unsized_len = if all_sized { 0 } else { 1 };
1118-
for (idx, field) in
1119-
variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
1120-
{
1117+
let unsized_len =
1118+
if all_sized { variant.fields.len() } else { variant.fields.len() - 1 };
1119+
for (idx, field) in variant.fields.raw.iter().enumerate() {
11211120
let last = idx == variant.fields.len() - 1;
11221121
let field_id = field.did.expect_local();
11231122
let hir::FieldDef { ty: hir_ty, .. } =
@@ -1127,28 +1126,45 @@ fn check_type_defn<'tcx>(
11271126
None,
11281127
tcx.type_of(field.did).instantiate_identity(),
11291128
);
1130-
wfcx.register_bound(
1131-
traits::ObligationCause::new(
1129+
if matches!(ty.kind(), ty::Adt(def, _) if def.repr().scalable()) {
1130+
struct_span_code_err!(
1131+
tcx.dcx(),
11321132
hir_ty.span,
1133-
wfcx.body_def_id,
1134-
traits::FieldSized {
1135-
adt_kind: match &item.kind {
1136-
ItemKind::Struct(..) => AdtKind::Struct,
1137-
ItemKind::Union(..) => AdtKind::Union,
1138-
ItemKind::Enum(..) => AdtKind::Enum,
1139-
kind => span_bug!(
1140-
item.span,
1141-
"should be wfchecking an ADT, got {kind:?}"
1142-
),
1133+
E0799,
1134+
"Scalable simd types cannot exist within {}",
1135+
match &item.kind {
1136+
ItemKind::Struct(..) => "a struct",
1137+
ItemKind::Union(..) => "a union",
1138+
ItemKind::Enum(..) => "enum variants",
1139+
kind =>
1140+
span_bug!(item.span, "should be wfchecking an ADT, got {kind:?}"),
1141+
}
1142+
)
1143+
.emit();
1144+
} else if idx < unsized_len {
1145+
wfcx.register_bound(
1146+
traits::ObligationCause::new(
1147+
hir_ty.span,
1148+
wfcx.body_def_id,
1149+
traits::FieldSized {
1150+
adt_kind: match &item.kind {
1151+
ItemKind::Struct(..) => AdtKind::Struct,
1152+
ItemKind::Union(..) => AdtKind::Union,
1153+
ItemKind::Enum(..) => AdtKind::Enum,
1154+
kind => span_bug!(
1155+
item.span,
1156+
"should be wfchecking an ADT, got {kind:?}"
1157+
),
1158+
},
1159+
span: hir_ty.span,
1160+
last,
11431161
},
1144-
span: hir_ty.span,
1145-
last,
1146-
},
1147-
),
1148-
wfcx.param_env,
1149-
ty,
1150-
tcx.require_lang_item(LangItem::Sized, None),
1151-
);
1162+
),
1163+
wfcx.param_env,
1164+
ty,
1165+
tcx.require_lang_item(LangItem::Sized, None),
1166+
);
1167+
}
11521168
}
11531169

11541170
// Explicit `enum` discriminant values must const-evaluate successfully.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(repr_simd, repr_scalable)]
2+
3+
#[repr(simd, scalable(4))]
4+
pub struct ScalableSimdFloat {
5+
_ty: [f32]
6+
}
7+
8+
fn main() {
9+
let x: [ScalableSimdFloat; 2]; //~ ERROR E0277
10+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0277]: the size for values of type `[f32]` cannot be known at compilation time
2+
--> $DIR/disallow-array.rs:9:12
3+
|
4+
LL | let x: [ScalableSimdFloat; 2];
5+
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: within `ScalableSimdFloat`, the trait `Sized` is not implemented for `[f32]`, which is required by `ScalableSimdFloat: Sized`
8+
note: required because it appears within the type `ScalableSimdFloat`
9+
--> $DIR/disallow-array.rs:4:12
10+
|
11+
LL | pub struct ScalableSimdFloat {
12+
| ^^^^^^^^^^^^^^^^^
13+
= note: slice and array elements must have `Sized` type
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(repr_simd, repr_scalable)]
2+
3+
#[repr(simd, scalable(4))]
4+
pub struct ScalableSimdFloat {
5+
_ty: [f32]
6+
}
7+
8+
pub enum Invalid {
9+
Scalable(ScalableSimdFloat), //~ ERROR E0799
10+
Int(i32),
11+
}
12+
13+
fn main() {
14+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0799]: Scalable simd types cannot exist within enum variants
2+
--> $DIR/disallow-enum.rs:9:14
3+
|
4+
LL | Scalable(ScalableSimdFloat),
5+
| ^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0799`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(repr_simd, repr_scalable)]
2+
3+
#[repr(simd, scalable(4))]
4+
pub struct ScalableSimdFloat {
5+
_ty: [f32]
6+
}
7+
8+
pub struct Invalid {
9+
x: ScalableSimdFloat, //~ ERROR E0799
10+
last: i32,
11+
}
12+
13+
#[repr(transparent)]
14+
struct Wrap(ScalableSimdFloat); //~ ERROR E0799
15+
16+
fn main() {
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0799]: Scalable simd types cannot exist within a struct
2+
--> $DIR/disallow-struct.rs:9:8
3+
|
4+
LL | x: ScalableSimdFloat,
5+
| ^^^^^^^^^^^^^^^^^
6+
7+
error[E0799]: Scalable simd types cannot exist within a struct
8+
--> $DIR/disallow-struct.rs:14:13
9+
|
10+
LL | struct Wrap(ScalableSimdFloat);
11+
| ^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0799`.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(repr_simd, repr_scalable)]
2+
3+
#[repr(simd, scalable(4))]
4+
pub struct ScalableSimdFloat {
5+
_ty: [f32]
6+
}
7+
8+
pub union Invalid {
9+
x: ScalableSimdFloat, //~ ERROR E0799
10+
other: i32,
11+
}
12+
13+
fn main() {
14+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0799]: Scalable simd types cannot exist within a union
2+
--> $DIR/disallow-union.rs:9:8
3+
|
4+
LL | x: ScalableSimdFloat,
5+
| ^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0799`.

0 commit comments

Comments
 (0)