|
1 | 1 | use std::cell::LazyCell; |
2 | 2 | use std::ops::ControlFlow; |
3 | 3 |
|
4 | | -use rustc_abi::{ExternAbi, FieldIdx}; |
| 4 | +use rustc_abi::{ExternAbi, FieldIdx, ScalableElt}; |
5 | 5 | use rustc_data_structures::unord::{UnordMap, UnordSet}; |
6 | 6 | use rustc_errors::codes::*; |
7 | 7 | use rustc_errors::{EmissionGuarantee, MultiSpan}; |
@@ -92,7 +92,9 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { |
92 | 92 | let span = tcx.def_span(def_id); |
93 | 93 | def.destructor(tcx); // force the destructor to be evaluated |
94 | 94 |
|
95 | | - if def.repr().simd() { |
| 95 | + if let Some(scalable) = def.repr().scalable { |
| 96 | + check_scalable_vector(tcx, span, def_id, scalable); |
| 97 | + } else if def.repr().simd() { |
96 | 98 | check_simd(tcx, span, def_id); |
97 | 99 | } |
98 | 100 |
|
@@ -1425,6 +1427,83 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { |
1425 | 1427 | } |
1426 | 1428 | } |
1427 | 1429 |
|
| 1430 | +#[tracing::instrument(skip(tcx), level = "debug")] |
| 1431 | +fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalable: ScalableElt) { |
| 1432 | + let ty = tcx.type_of(def_id).instantiate_identity(); |
| 1433 | + let ty::Adt(def, args) = ty.kind() else { return }; |
| 1434 | + if !def.is_struct() { |
| 1435 | + tcx.dcx().delayed_bug("`rustc_scalable_vector` applied to non-struct"); |
| 1436 | + return; |
| 1437 | + } |
| 1438 | + |
| 1439 | + let fields = &def.non_enum_variant().fields; |
| 1440 | + match scalable { |
| 1441 | + ScalableElt::ElementCount(..) if fields.is_empty() => { |
| 1442 | + let mut err = |
| 1443 | + tcx.dcx().struct_span_err(span, "scalable vectors must have a single field"); |
| 1444 | + err.help("scalable vector types' only field must be a primitive scalar type"); |
| 1445 | + err.emit(); |
| 1446 | + return; |
| 1447 | + } |
| 1448 | + ScalableElt::ElementCount(..) if fields.len() >= 2 => { |
| 1449 | + tcx.dcx().struct_span_err(span, "scalable vectors cannot have multiple fields").emit(); |
| 1450 | + return; |
| 1451 | + } |
| 1452 | + ScalableElt::Container if fields.is_empty() => { |
| 1453 | + let mut err = |
| 1454 | + tcx.dcx().struct_span_err(span, "scalable vectors must have a single field"); |
| 1455 | + err.help("tuples of scalable vectors can only contain multiple of the same scalable vector type"); |
| 1456 | + err.emit(); |
| 1457 | + return; |
| 1458 | + } |
| 1459 | + _ => {} |
| 1460 | + } |
| 1461 | + |
| 1462 | + match scalable { |
| 1463 | + ScalableElt::ElementCount(..) => { |
| 1464 | + let element_ty = &fields[FieldIdx::ZERO].ty(tcx, args); |
| 1465 | + |
| 1466 | + // Check that `element_ty` only uses types valid in the lanes of a scalable vector |
| 1467 | + // register: scalar types which directly match a "machine" type - integers, floats and |
| 1468 | + // bools |
| 1469 | + match element_ty.kind() { |
| 1470 | + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool => (), |
| 1471 | + _ => { |
| 1472 | + let mut err = tcx.dcx().struct_span_err( |
| 1473 | + span, |
| 1474 | + "element type of a scalable vector must be a primitive scalar", |
| 1475 | + ); |
| 1476 | + err.help( |
| 1477 | + "only `u*`, `i*`, `f*`, `*const`, `*mut` and `bool` types are accepted", |
| 1478 | + ); |
| 1479 | + err.emit(); |
| 1480 | + } |
| 1481 | + } |
| 1482 | + } |
| 1483 | + ScalableElt::Container => { |
| 1484 | + let mut prev_field_ty = None; |
| 1485 | + for field in fields.iter() { |
| 1486 | + let element_ty = field.ty(tcx, args); |
| 1487 | + if let ty::Adt(def, _) = element_ty.kind() |
| 1488 | + && !def.repr().scalable() |
| 1489 | + { |
| 1490 | + tcx.dcx().span_err( |
| 1491 | + tcx.def_span(field.did), |
| 1492 | + "scalable vector structs can only have scalable vector fields", |
| 1493 | + ); |
| 1494 | + } else if let Some(prev_ty) = prev_field_ty.replace(element_ty) |
| 1495 | + && prev_ty != element_ty |
| 1496 | + { |
| 1497 | + tcx.dcx().span_err( |
| 1498 | + tcx.def_span(field.did), |
| 1499 | + "all fields in a scalable vector struct must be the same type", |
| 1500 | + ); |
| 1501 | + } |
| 1502 | + } |
| 1503 | + } |
| 1504 | + } |
| 1505 | +} |
| 1506 | + |
1428 | 1507 | pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { |
1429 | 1508 | let repr = def.repr(); |
1430 | 1509 | if repr.packed() { |
|
0 commit comments