rust-lang/rust · critical
`homogeneous_aggregate` should not be called for scalable ve
Error message
`homogeneous_aggregate` should not be called for scalable vectors
What it means
`homogeneous_aggregate` walks an aggregate's leaf fields to detect a single uniform pass-by-register unit, an ABI optimization for things like `(f32, f32, f32)`. Scalable (VL) SIMD vectors (`BackendRepr::SimdScalableVector`) have a runtime-unknown element count, so the question 'are all leaves the same register' is meaningless for them. This `unreachable!` enforces that no calling-convention code path ever asks it.
Source
Thrown at compiler/rustc_abi/src/callconv.rs:89
BackendRepr::Scalar(scalar) => {
let kind = match scalar.primitive() {
Primitive::Int(..) | Primitive::Pointer(_) => RegKind::Integer,
Primitive::Float(_) => RegKind::Float,
};
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
}
BackendRepr::SimdVector { element, count: _ } => {
assert!(!self.is_zst());
Ok(HomogeneousAggregate::Homogeneous(Reg {
kind: RegKind::Vector { hint_vector_elem: element.primitive() },
size: self.size,
}))
}
BackendRepr::SimdScalableVector { .. } => {
unreachable!("`homogeneous_aggregate` should not be called for scalable vectors")
}
BackendRepr::ScalarPair { .. } | BackendRepr::Memory { sized: true } => {
// Helper for computing `homogeneous_aggregate`, allowing a custom
// starting offset (used below for handling variants).
let from_fields_at =
|layout: Self,
start: Size|
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
let is_union = match layout.fields {
FieldsShape::Primitive => {
unreachable!("aggregates can't have `FieldsShape::Primitive`")
}
FieldsShape::Array { count, .. } => {
assert_eq!(start, Size::ZERO);
let result = if count > 0 {
layout.field(cx, 0).homogeneous_aggregate(cx)?View on GitHub (pinned to 22057b88b0)
Solutions
- Guard the caller so scalable-vector arguments skip `homogeneous_aggregate` and are handled by the target's dedicated SVE/RVV PCS path.
- Check the `BackendRepr` before invoking: `if matches!(layout.backend_repr, BackendRepr::SimdScalableVector { .. }) { return dedicated handling }`.
- Audit the target-specific callconv to ensure scalable vectors never appear as fields of an aggregate passed to this function.
- Add a regression test with a scalable-vector type to lock in the early-return.
Example fix
// before
let homo = layout.homogeneous_aggregate(cx)?; // panics for scalable vectors
// after
if matches!(layout.backend_repr, BackendRepr::SimdScalableVector { .. }) {
return Err(Heterogeneous);
}
let homo = layout.homogeneous_aggregate(cx)?; Defensive patterns
Strategy: validation
Validate before calling
// homogeneous_aggregate unreachable!() on BackendRepr::SimdScalableVector.
// Check the layout's backend repr before recursing into it.
use rustc_abi::{BackendRepr, LayoutData};
fn homogeneous_eligible<F, V>(layout: &LayoutData<F, V>) -> bool {
!matches!(layout.backend_repr, BackendRepr::SimdScalableVector { .. })
}
// caller:
// if homogeneous_eligible(&ty_layout) { ty_layout.homogeneous_aggregate(cx)? } else { return Err(Heterogeneous); } Type guard
fn is_fixed_simd_or_scalar<F, V>(layout: &LayoutData<F, V>) -> bool {
matches!(
layout.backend_repr,
BackendRepr::Scalar(_) | BackendRepr::ScalarPair { .. } | BackendRepr::Memory { .. }
) || matches!(layout.backend_repr, BackendRepr::SimdVector { .. })
} Try / catch
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
layout.homogeneous_aggregate(cx)
}));
match result {
Ok(Ok(ha)) => { /* use homogeneous aggregate */ }
Ok(Err(_)) => { /* legitimately heterogeneous */ }
Err(_) => { /* scalable vector slipped through; treat as heterogeneous */ }
} Prevention
- Scalable vectors (SVE/RVV) are not homogeneous-aggregate-eligible by construction; short-circuit them before the recursion.
- When walking aggregate fields, propagate a 'may contain scalable vector' flag from the type system down to the homogeneous check so you never call it on a layout that could be SimdScalableVector.
- Treat SimdScalableVector as its own calling-convention category; do not route it through code paths designed for fixed SIMD.
When it happens
Trigger: Calling `TyAndLayout::homogeneous_aggregate(cx)` on a type whose `backend_repr` is `BackendRepr::SimdScalableVector { .. }` — e.g. a Rust scalable-vector type such as `#[repr(simd)]` scalable elements used as a function argument under an ABI that consults homogeneity (AArch64 SVE PCS).
Common situations: A calling-convention or codegen change that routes scalable-vector arguments through the generic homogeneous-aggregate path instead of the dedicated vector handling, or a new scalable-vector primitive leaking into a struct/aggregate field that the homogeneity walker then recurses into.
Related errors
- unsupported integer: {self:?}
- unsupported float: {self:?}
- aggregates can't have `FieldsShape::Primitive`
- unreachable: invalid ExternAbi variant
- assignment does not match variant
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/8b8bfbd9a73004e8.json.
Report an issue: GitHub.