{"id":"22350a3dc550e057","repo":"rust-lang/rust","slug":"numscalablevectors-0-is-illformed","errorCode":null,"errorMessage":"`NumScalableVectors(0)` is illformed","messagePattern":"`NumScalableVectors\\(0\\)` is illformed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_abi/src/lib.rs","lineNumber":1765,"sourceCode":"        NumScalableVectors(1)\n    }\n\n    // Returns `NumScalableVectors` for values of two through eight, which are a valid number of\n    // fields for a tuple of scalable vectors to have. `1` is a valid value of `NumScalableVectors`\n    // but not for a tuple which would have a field count.\n    pub fn from_field_count(count: usize) -> Option<Self> {\n        match count {\n            2..8 => Some(NumScalableVectors(count as u8)),\n            _ => None,\n        }\n    }\n}\n\n#[cfg(feature = \"nightly\")]\nimpl IntoDiagArg for NumScalableVectors {\n    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {\n        DiagArgValue::Str(std::borrow::Cow::Borrowed(match self.0 {\n            0 => panic!(\"`NumScalableVectors(0)` is illformed\"),\n            1 => \"one\",\n            2 => \"two\",\n            3 => \"three\",\n            4 => \"four\",\n            5 => \"five\",\n            6 => \"six\",\n            7 => \"seven\",\n            8 => \"eight\",\n            _ => panic!(\"`NumScalableVectors(N)` for N>8 is illformed\"),\n        }))\n    }\n}\n\n/// The way we represent values to the backend\n///\n/// Previously this was conflated with the \"ABI\" a type is given, as in the platform-specific ABI.\n/// In reality, this implies little about that, but is mostly used to describe the syntactic form\n/// emitted for the backend, as most backends handle SSA values and blobs of memory differently.","sourceCodeStart":1747,"sourceCodeEnd":1783,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/lib.rs#L1747-L1783","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet n = NumScalableVectors(computed);\n\n// after\nlet n = match computed {\n    1 => NumScalableVectors::for_non_tuple(),\n    2.. => NumScalableVectors::from_field_count(computed as usize)\n        .expect(\"scalable-vector tuple size in 2..8\"),\n    _ => return Err(LayoutError::Unknown(bug!())),\n};","handlingStrategy":"validation","validationCode":"// NumScalableVectors(0) is illformed. Use the provided constructors,\n// which never produce 0:\nfn from_count(n: usize) -> Option<rustc_abi::NumScalableVectors> {\n    rustc_abi::NumScalableVectors::from_field_count(n) // None for 0\n        .or_else(|| (n == 1).then(rustc_abi::NumScalableVectors::for_non_tuple))\n}\n// Or, reject 0 explicitly before any construction:\n// if n == 0 { return Err(BadNumScalableVectors); }","typeGuard":"// The type itself allows the illformed 0; there is no safe constructor.\n// Treat any NumScalableVectors you did not construct yourself as suspect.\nfn is_wellformed(nsv: rustc_abi::NumScalableVectors) -> bool {\n    (1..=8).contains(&nsv.0)\n}","tryCatchPattern":"// The panic fires inside IntoDiagArg, typically deep in diagnostics formatting.\n// Validate at construction; catching it downstream is not viable.","preventionTips":["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."],"tags":["rustc-abi","scalable-vector","simd","invariant","panic","diagnostic"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}