rust-lang/rust · error
`NumScalableVectors(0)` is illformed
Error message
`NumScalableVectors(0)` is illformed
What it means
Thrown at compiler/rustc_abi/src/lib.rs:1765 inside `NumScalableVectors::into_diag_arg`. `NumScalableVectors` models the number of scalable vectors in a type (1 for a single vector, 2..8 for a tuple). The value 0 is ill-formed because it would describe a type that contains zero scalable vectors yet is still categorized as the scalable-vector variant of `BackendRepr`, which is contradictory.
Source
Thrown at compiler/rustc_abi/src/lib.rs:1765
NumScalableVectors(1)
}
// Returns `NumScalableVectors` for values of two through eight, which are a valid number of
// fields for a tuple of scalable vectors to have. `1` is a valid value of `NumScalableVectors`
// but not for a tuple which would have a field count.
pub fn from_field_count(count: usize) -> Option<Self> {
match count {
2..8 => Some(NumScalableVectors(count as u8)),
_ => None,
}
}
}
#[cfg(feature = "nightly")]
impl IntoDiagArg for NumScalableVectors {
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
DiagArgValue::Str(std::borrow::Cow::Borrowed(match self.0 {
0 => panic!("`NumScalableVectors(0)` is illformed"),
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
6 => "six",
7 => "seven",
8 => "eight",
_ => panic!("`NumScalableVectors(N)` for N>8 is illformed"),
}))
}
}
/// The way we represent values to the backend
///
/// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI.
/// In reality, this implies little about that, but is mostly used to describe the syntactic form
/// emitted for the backend, as most backends handle SSA values and blobs of memory differently.View on GitHub (pinned to 22057b88b0)
Solutions
- Always construct `NumScalableVectors` via `for_non_tuple()` or `from_field_count(n)`; never write `NumScalableVectors(x)` with a computed `x`.
- If you must compute the count, validate `1..=8` before constructing and propagate an error otherwise.
- Make the field non-public in a local fork / propose an upstream change to enforce the invariant at construction time.
Example fix
// before
let n = NumScalableVectors(computed);
// after
let n = match computed {
1 => NumScalableVectors::for_non_tuple(),
2.. => NumScalableVectors::from_field_count(computed as usize)
.expect("scalable-vector tuple size in 2..8"),
_ => return Err(LayoutError::Unknown(bug!())),
}; Defensive patterns
Strategy: validation
Validate before calling
// NumScalableVectors(0) is illformed. Use the provided constructors,
// which never produce 0:
fn from_count(n: usize) -> Option<rustc_abi::NumScalableVectors> {
rustc_abi::NumScalableVectors::from_field_count(n) // None for 0
.or_else(|| (n == 1).then(rustc_abi::NumScalableVectors::for_non_tuple))
}
// Or, reject 0 explicitly before any construction:
// if n == 0 { return Err(BadNumScalableVectors); } Type guard
// The type itself allows the illformed 0; there is no safe constructor.
// Treat any NumScalableVectors you did not construct yourself as suspect.
fn is_wellformed(nsv: rustc_abi::NumScalableVectors) -> bool {
(1..=8).contains(&nsv.0)
} Try / catch
// The panic fires inside IntoDiagArg, typically deep in diagnostics formatting. // Validate at construction; catching it downstream is not viable.
Prevention
- Never construct NumScalableVectors by direct tuple-struct syntax; always go through from_field_count or for_non_tuple.
- 0 is meaningless for a tuple-of-vectors count; reject empty tuples of scalable vectors at the type-construction site.
- Audit any externally-supplied usize before casting to NumScalableVectors.
When it happens
Trigger: Constructing `NumScalableVectors(0)` directly (the field is `pub`) and then emitting a diagnostic that calls `into_diag_arg`, or producing it via an arithmetic path that subtracted/clamped to zero. The provided constructor `from_field_count` already returns `None` for counts outside `2..8`, and `for_non_tuple` yields `1`, so a 0 can only arise from bypassing those constructors.
Common situations: Fuzzer-generated inputs, a codegen path that computes `number_of_vectors` by subtraction (e.g. `total - non_scalable`) and underflows to 0, or third-party tools (rust-analyzer, miri) that synthesize `BackendRepr::SimdScalableVector` with a hand-picked count.
Related errors
- `NumScalableVectors(N)` for N>8 is illformed
- Layout of fields should be Arbitrary for variants
- `homogeneous_aggregate` should not be called for scalable ve
- Size::bits: {bytes} bytes in bits doesn't fit in u64
- Size::add: {} + {} doesn't fit in u64
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/22350a3dc550e057.json.
Report an issue: GitHub.