{"id":"6fb8f787f60999fe","repo":"rust-lang/rust","slug":"invalid-scalar-type-val","errorCode":null,"errorMessage":"Invalid scalar type {val:?}","messagePattern":"Invalid scalar type (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_middle/src/mir/statement.rs","lineNumber":670,"sourceCode":"    }\n\n    /// Convenience helper to make a literal-like constant from a given scalar value.\n    /// Since this is used to synthesize MIR, assumes `user_ty` is None.\n    pub fn const_from_scalar(\n        tcx: TyCtxt<'tcx>,\n        ty: Ty<'tcx>,\n        val: Scalar,\n        span: Span,\n    ) -> Operand<'tcx> {\n        debug_assert!({\n            let typing_env = ty::TypingEnv::fully_monomorphized();\n            let type_size = tcx\n                .layout_of(typing_env.as_query_input(ty))\n                .unwrap_or_else(|e| panic!(\"could not compute layout for {ty:?}: {e:?}\"))\n                .size;\n            let scalar_size = match val {\n                Scalar::Int(int) => int.size(),\n                _ => panic!(\"Invalid scalar type {val:?}\"),\n            };\n            scalar_size == type_size\n        });\n        Operand::Constant(Box::new(ConstOperand {\n            span,\n            user_ty: None,\n            const_: Const::Val(ConstValue::Scalar(val), ty),\n        }))\n    }\n\n    pub fn to_copy(&self) -> Self {\n        match *self {\n            Operand::Copy(_) | Operand::Constant(_) | Operand::RuntimeChecks(_) => self.clone(),\n            Operand::Move(place) => Operand::Copy(place),\n        }\n    }\n\n    /// Returns the `Place` that is the target of this `Operand`, or `None` if this `Operand` is a","sourceCodeStart":652,"sourceCodeEnd":688,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_middle/src/mir/statement.rs#L652-L688","documentation":"Inside the same `debug_assert!` block in `Operand::const_from_scalar`, the code matches on `val: Scalar` and panics if it is anything other than `Scalar::Int`. rustc_middle enforces this because `const_from_scalar` is meant to synthesize integer-like literal constants; passing a `Scalar::Ptr` (an allocation pointer) is a misuse of the API and would produce an invalid constant operand.","triggerScenarios":"Triggered in a debug rustc build when a caller passes `Scalar::Ptr(ptr, ..)` (a pointer into an allocation) instead of `Scalar::Int(int)` to `Operand::const_from_scalar`. Reproducible by a codegen/mir-opt path that reuses a pointer scalar where an integer literal scalar is required.","commonSituations":"Out-of-tree backend or mir-opt that treats any `Scalar` uniformly; refactoring that changed an integer constant into a reference/pointer constant without switching the constructor; debug-toolchain build hitting an assertion that release builds would silently skip.","solutions":["Pass only `Scalar::Int(...)` to `const_from_scalar`; for pointer constants use the allocation-based constant API (e.g. `ConstValue::ByRef`/`Slice` via the proper constructor).","If your scalar originated from a pointer read, materialize an allocation and build the constant operand from that allocation instead of the raw `Scalar::Ptr`.","Verify in release rustc that the surrounding code is not silently producing ill-formed MIR (the debug assert exists precisely because release builds would hide this).","File an ICE if a stock rustc path passes a pointer scalar here — include the call site and the offending `Scalar` value."],"exampleFix":"// before\nlet op = Operand::const_from_scalar(tcx, ty, Scalar::Ptr(ptr, sz), span);\n// debug rustc panic: Invalid scalar type Ptr(...)\n\n// after: build a pointer-typed constant from the allocation\nlet const_ = Const::Val(\n    ConstValue::Scalar(Scalar::Ptr(ptr, sz)), // built via the alloc API\n    ty,\n);\nlet op = Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }));","handlingStrategy":"type-guard","validationCode":"// const_from_scalar() additionally requires the Scalar to be a Scalar::Int\n// (it then reads .size() to compare against the type's layout size).\n// Validate the variant before calling.\nuse rustc_middle::mir::interpret::Scalar;\nfn is_int_scalar(val: &Scalar) -> bool {\n    matches!(val, Scalar::Int(_))\n}\n// Usage:\n//   if is_int_scalar(&scalar) {\n//       Operand::const_from_scalar(tcx, ty, scalar, span)\n//   } else {\n//       // Scalar::Ptr (pointer/alloc) cannot become a plain int constant here;\n//       // build the Operand via ConstValue::Scalar + Const::Val instead.\n//   }","typeGuard":"// Narrow a Scalar to its integer form, extracting the size in one step.\nuse rustc_middle::mir::interpret::{Scalar, ScalarInt};\nfn as_scalar_int(val: &Scalar) -> Option<ScalarInt> {\n    match val {\n        Scalar::Int(int) => Some(*int),\n        _ => None, // Scalar::Ptr -> not valid for const_from_scalar\n    }\n}","tryCatchPattern":null,"preventionTips":["`const_from_scalar` only accepts `Scalar::Int`; a `Scalar::Ptr` (an allocation-backed pointer) is not a plain integer and must be wrapped through `ConstValue::Scalar` + `Const::Val`.","When you deserialize or transmute raw bytes into a Scalar, explicitly construct `Scalar::Int(ScalarInt::try_from_raw(...))` rather than relying on a `From` impl that could yield a Ptr.","Pair this guard with the layout guard from [258]: a Scalar::Int whose `.size()` differs from the type's layout size is the other half of the same debug_assert — verify both.","Keep pointer-valued constants (static addresses, fn pointers, allocations) on the `ConstValue::Slice`/`ByRef`/`Scalar(Scalar::Ptr)` paths; never route them through `const_from_scalar`."],"tags":["rustc","mir","scalar","debug-assert","const-eval"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}