{"id":"7087eb6e7598d024","repo":"rust-lang/rust","slug":"cannot-change-the-valid-range-of-a-union","errorCode":null,"errorMessage":"cannot change the valid range of a union","messagePattern":"cannot change the valid range of a union","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_abi/src/lib.rs","lineNumber":1607,"sourceCode":"    pub fn to_union(&self) -> Self {\n        Self::Union { value: self.primitive() }\n    }\n\n    #[inline]\n    pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {\n        match *self {\n            Scalar::Initialized { valid_range, .. } => valid_range,\n            Scalar::Union { value } => WrappingRange::full(value.size(cx)),\n        }\n    }\n\n    #[inline]\n    /// Allows the caller to mutate the valid range. This operation will panic if attempted on a\n    /// union.\n    pub fn valid_range_mut(&mut self) -> &mut WrappingRange {\n        match self {\n            Scalar::Initialized { valid_range, .. } => valid_range,\n            Scalar::Union { .. } => panic!(\"cannot change the valid range of a union\"),\n        }\n    }\n\n    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole\n    /// layout.\n    #[inline]\n    pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {\n        match *self {\n            Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),\n            Scalar::Union { .. } => true,\n        }\n    }\n\n    /// Returns `true` if this type can be left uninit.\n    #[inline]\n    pub fn is_uninit_valid(&self) -> bool {\n        match *self {\n            Scalar::Initialized { .. } => false,","sourceCodeStart":1589,"sourceCodeEnd":1625,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/lib.rs#L1589-L1625","documentation":"Thrown by `Scalar::valid_range_mut` (compiler/rustc_abi/src/lib.rs:1607) when invoked on `Scalar::Union`. A union scalar deliberately has no `valid_range` (it allows undef and has no niches — see the field comment at lib.rs:1531-1533), so the range is not stored and cannot be mutated. Mutating it would imply adding a niche to a union, which is semantically invalid.","triggerScenarios":"Calling `valid_range_mut()` on a `Scalar` produced by `to_union()` or constructed as `Scalar::Union { .. }`. This typically happens in niche/layout adjustment code that did not first check whether the scalar was `Initialized`.","commonSituations":"A type that was treated as a regular scalar but was lowered as a union (e.g. `MaybeUninit<T>`, `union` types, or `ManuallyDrop`-like wrappers), then passed to code that tries to narrow the valid range for niche optimization. Also seen when generic layout code assumes every `Scalar` is `Initialized`.","solutions":["Before mutating the range, pattern-match on the `Scalar`: only call `valid_range_mut()` for `Scalar::Initialized { .. }`, and handle `Scalar::Union { .. }` separately (skip niche adjustment).","If your algorithm requires a mutable range, reconstruct as `Scalar::Initialized { value: union.value, valid_range: WrappingRange::full(...) }` instead of trying to mutate the union form.","Add an assertion/test exercising union-typed fields in the affected layout pass to catch the assumption early."],"exampleFix":"// before\nlet range = scalar.valid_range_mut();\n*range = new_range;\n\n// after\nif let Scalar::Initialized { valid_range, .. } = &mut scalar {\n    *valid_range = new_range;\n} else {\n    // unions have no niche to narrow\n    return Ok(layout);\n}","handlingStrategy":"type-guard","validationCode":"// valid_range_mut panics on Scalar::Union. Narrow before mutating.\nmatch scalar {\n    rustc_abi::Scalar::Initialized { valid_range, .. } => {\n        // safely mutate valid_range here\n    }\n    rustc_abi::Scalar::Union { .. } => {\n        // a union's range is always full for its size; do not mutate\n    }\n}","typeGuard":"fn is_initialized_scalar(s: &rustc_abi::Scalar) -> bool {\n    matches!(s, rustc_abi::Scalar::Initialized { .. })\n}\n// Usage:\n// if is_initialized_scalar(&scalar) { scalar.valid_range_mut().start = ...; }","tryCatchPattern":"// Not a runtime error to catch; the invariant is enforced by the type.\n// Use the match above and skip mutation in the Union arm.","preventionTips":["Read the doc comment on valid_range_mut: 'This operation will panic if attempted on a union.'","Treat Scalar::Union as immutable-by-construction; only Scalar::Initialized has a mutable valid_range.","If you need an unconstrained range on an Initialized scalar, set it to WrappingRange::full(size), not mutate a Union."],"tags":["rustc-abi","scalar","union","niche","layout","panic"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}