rust-lang/rust · error

got a pointer where a ScalarInt was expected

Error message

got a pointer where a ScalarInt was expected

What it means

`Scalar::assert_scalar_int` (value.rs:325) panics when called on a `Scalar::Ptr(..)` — it is the unchecked variant that assumes the caller has already ensured the scalar holds an integer. The checked sibling `try_to_scalar_int` returns `Ok(ScalarInt)` only for `Scalar::Int` (or, when `Prov::OFFSET_IS_ADDR`, for pointers that can be folded into an address); `assert_scalar_int` simply `.expect`s that result.

Source

Thrown at compiler/rustc_middle/src/mir/interpret/value.rs:325

        }
    }

    pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
        if matches!(self, Scalar::Ptr(..)) {
            *self = self.to_scalar_int()?.into();
        }
        interp_ok(())
    }

    #[inline(always)]
    pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> {
        self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None))).into()
    }

    #[inline(always)]
    #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
    pub fn assert_scalar_int(self) -> ScalarInt {
        self.try_to_scalar_int().expect("got a pointer where a ScalarInt was expected")
    }

    /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in
    /// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type.
    #[inline]
    pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
        assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
        self.to_scalar_int()?
            .try_to_bits(target_size)
            .map_err(|size| {
                err_ub!(ScalarSizeMismatch(ScalarSizeMismatch {
                    target_size: target_size.bytes(),
                    data_size: size.bytes(),
                }))
            })
            .into()
    }

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Switch to the checked form `scalar.to_scalar_int()?` which yields a proper `InterpError` (`ReadPointerAsInt`) instead of panicking.
  2. If you truly need an integer and can prove the operand is one, strip provenance first via `Scalar::clear_provenance` before asserting.
  3. Use `try_to_scalar_int()` and branch on the `Err(Scalar::Ptr)` to emit a precise diagnostic.
  4. Inspect the `#[track_caller]` location from the panic backtrace to find the asserting caller.

Example fix

// before
let int = scalar.assert_scalar_int();

// after
let int = scalar.to_scalar_int()?;
Defensive patterns

Strategy: type-guard

Validate before calling

// assert_scalar_int panics when the value is a pointer. Use the fallible API
// instead and branch on whether the value holds an integer.
fn read_as_int<'tcx>(v: Scalar) -> InterpResult<'tcx, ScalarInt> {
    v.to_scalar_int() // returns Err(ReadPointerAsInt) instead of panicking
}

Type guard

// Narrow a Scalar before assuming it is an integer.
fn is_scalar_int(v: &Scalar) -> bool {
    matches!(v.try_to_scalar_int(), Ok(_))
}

if is_scalar_int(&scalar) {
    let bits = scalar.assert_scalar_int();
} else {
    // it is a pointer (or uninitialized); handle accordingly
}

Try / catch

// Only if you must keep assert_scalar_int in hot path: catch the panic.
let bits = std::panic::catch_unwind(|| scalar.assert_scalar_int());
match bits {
    Ok(i) => /* use i */,
    Err(_) => /* scalar held a pointer; treat as UB or read it as a pointer */,
}

Prevention

When it happens

Trigger: Calling `scalar.assert_scalar_int()` on a value that is actually `Scalar::Ptr(ptr, sz)`. Common when a const-eval path assumes a value is an integer (e.g. discriminant, bit read, integer arithmetic) but the operand holds a pointer — most often because provenance stripping was skipped or a pointer flowed into an integer-only MIR op.

Common situations: Miri exercises that expose pointer-as-int paths; const-eval of code that reads the bits of a `usize` cast from a reference; bugs in intrinsic shims (`memcmp`, atomic ops) that call `assert_scalar_int` on operands that may carry provenance; debug builds (`#[cfg_attr(debug_assertions, track_caller)]`) surface this earlier than release.

Related errors


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