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

  1. Always construct `NumScalableVectors` via `for_non_tuple()` or `from_field_count(n)`; never write `NumScalableVectors(x)` with a computed `x`.
  2. If you must compute the count, validate `1..=8` before constructing and propagate an error otherwise.
  3. 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

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


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/22350a3dc550e057.json. Report an issue: GitHub.