|
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}; |
@@ -94,7 +94,9 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { |
94 | 94 | let span = tcx.def_span(def_id); |
95 | 95 | def.destructor(tcx); // force the destructor to be evaluated |
96 | 96 |
|
97 | | - if def.repr().simd() { |
| 97 | + if let Some(scalable) = def.repr().scalable { |
| 98 | + check_scalable_vector(tcx, span, def_id, scalable); |
| 99 | + } else if def.repr().simd() { |
98 | 100 | check_simd(tcx, span, def_id); |
99 | 101 | } |
100 | 102 |
|
@@ -1398,6 +1400,83 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { |
1398 | 1400 | } |
1399 | 1401 | } |
1400 | 1402 |
|
| 1403 | +#[tracing::instrument(skip(tcx), level = "debug")] |
| 1404 | +fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalable: ScalableElt) { |
| 1405 | + let ty = tcx.type_of(def_id).instantiate_identity(); |
| 1406 | + let ty::Adt(def, args) = ty.kind() else { return }; |
| 1407 | + if !def.is_struct() { |
| 1408 | + tcx.dcx().delayed_bug("`rustc_scalable_vector` applied to non-struct"); |
| 1409 | + return; |
| 1410 | + } |
| 1411 | + |
| 1412 | + let fields = &def.non_enum_variant().fields; |
| 1413 | + match scalable { |
| 1414 | + ScalableElt::ElementCount(..) if fields.is_empty() => { |
| 1415 | + let mut err = |
| 1416 | + tcx.dcx().struct_span_err(span, "scalable vectors must have a single field"); |
| 1417 | + err.help("scalable vector types' only field must be a primitive scalar type"); |
| 1418 | + err.emit(); |
| 1419 | + return; |
| 1420 | + } |
| 1421 | + ScalableElt::ElementCount(..) if fields.len() >= 2 => { |
| 1422 | + tcx.dcx().struct_span_err(span, "scalable vectors cannot have multiple fields").emit(); |
| 1423 | + return; |
| 1424 | + } |
| 1425 | + ScalableElt::Container if fields.is_empty() => { |
| 1426 | + let mut err = |
| 1427 | + tcx.dcx().struct_span_err(span, "scalable vectors must have a single field"); |
| 1428 | + err.help("tuples of scalable vectors can only contain multiple of the same scalable vector type"); |
| 1429 | + err.emit(); |
| 1430 | + return; |
| 1431 | + } |
| 1432 | + _ => {} |
| 1433 | + } |
| 1434 | + |
| 1435 | + match scalable { |
| 1436 | + ScalableElt::ElementCount(..) => { |
| 1437 | + let element_ty = &fields[FieldIdx::ZERO].ty(tcx, args); |
| 1438 | + |
| 1439 | + // Check that `element_ty` only uses types valid in the lanes of a scalable vector |
| 1440 | + // register: scalar types which directly match a "machine" type - integers, floats and |
| 1441 | + // bools |
| 1442 | + match element_ty.kind() { |
| 1443 | + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool => (), |
| 1444 | + _ => { |
| 1445 | + let mut err = tcx.dcx().struct_span_err( |
| 1446 | + span, |
| 1447 | + "element type of a scalable vector must be a primitive scalar", |
| 1448 | + ); |
| 1449 | + err.help( |
| 1450 | + "only `u*`, `i*`, `f*`, `*const`, `*mut` and `bool` types are accepted", |
| 1451 | + ); |
| 1452 | + err.emit(); |
| 1453 | + } |
| 1454 | + } |
| 1455 | + } |
| 1456 | + ScalableElt::Container => { |
| 1457 | + let mut prev_field_ty = None; |
| 1458 | + for field in fields.iter() { |
| 1459 | + let element_ty = field.ty(tcx, args); |
| 1460 | + if let ty::Adt(def, _) = element_ty.kind() |
| 1461 | + && !def.repr().scalable() |
| 1462 | + { |
| 1463 | + tcx.dcx().span_err( |
| 1464 | + tcx.def_span(field.did), |
| 1465 | + "scalable vector structs can only have scalable vector fields", |
| 1466 | + ); |
| 1467 | + } else if let Some(prev_ty) = prev_field_ty.replace(element_ty) |
| 1468 | + && prev_ty != element_ty |
| 1469 | + { |
| 1470 | + tcx.dcx().span_err( |
| 1471 | + tcx.def_span(field.did), |
| 1472 | + "all fields in a scalable vector struct must be the same type", |
| 1473 | + ); |
| 1474 | + } |
| 1475 | + } |
| 1476 | + } |
| 1477 | + } |
| 1478 | +} |
| 1479 | + |
1401 | 1480 | pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { |
1402 | 1481 | let repr = def.repr(); |
1403 | 1482 | if repr.packed() { |
|
0 commit comments