rust-lang/rust · error

an interpreter error got improperly discarded; use `discard_

Error message

an interpreter error got improperly discarded; use `discard_err()` if this is intentional

What it means

`InterpResult<'tcx, T>` is a newtype around `Result` plus a `Guard` whose `Drop` impl panics with this message if the `InterpResult` is dropped without being explicitly consumed. The design forces every interpreter call site to either propagate, match, or deliberately discard its result — silently dropping a UB/invalidity error would hide miscompilation. The panic is suppressed automatically when the thread is already panicking to avoid double-panic aborts.

Source

Thrown at compiler/rustc_middle/src/mir/interpret/error.rs:933

#[macro_export]
macro_rules! throw_exhaust {
    ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) };
}

#[macro_export]
macro_rules! throw_machine_stop {
    ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) };
}

/// Guard type that panics on drop.
#[derive(Debug)]
struct Guard;

impl Drop for Guard {
    fn drop(&mut self) {
        // We silence the guard if we are already panicking, to avoid double-panics.
        if !std::thread::panicking() {
            panic!(
                "an interpreter error got improperly discarded; use `discard_err()` if this is intentional"
            );
        }
    }
}

/// The result type used by the interpreter. This is a newtype around `Result`
/// to block access to operations like `ok()` that discard UB errors.
///
/// We also make things panic if this type is ever implicitly dropped.
#[derive(Debug)]
#[must_use]
pub struct InterpResult<'tcx, T = ()> {
    res: Result<T, InterpErrorInfo<'tcx>>,
    guard: Guard,
}

impl<'tcx, T> ops::Try for InterpResult<'tcx, T> {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Propagate the result with `?` (the idiomatic fix): add `?` to the offending call.
  2. If the error is genuinely to be ignored, call `.discard_err()` explicitly to document intent and defuse the guard.
  3. Match on the result if you need branch-specific handling: `match res { Ok(_) => ..., Err(e) => ... }`.
  4. Use the `#[track_caller]`/backtrace from the panic to jump to the exact dropped value.

Example fix

// before
ecx.write_scalar(val, dest); // InterpResult dropped → panic on drop

// after
ecx.write_scalar(val, dest)?;
// or, if intentionally discarding:
ecx.write_scalar(val, dest).discard_err();
Defensive patterns

Strategy: validation

Validate before calling

// InterpResult panics on drop if it still holds an InterpError -- the Guard
// fires. Always consume the result: propagate with `?`, or explicitly drop
// the error with `.discard_err()` when you really intend to ignore it.
fn run_block<'tcx, T>(
    interp: &mut InterpCx<'tcx>,
) -> InterpResult<'tcx, T> {
    let res: InterpResult<'tcx, T> = interp.do_step();
    // NEVER let an InterpResult value go out of scope unhandled.
    res
}

// If you genuinely want to swallow a benign error:
let _ = interp.do_step().discard_err(); // explicit, auditable

Try / catch

// Prefer fixing the call site over catching. catch_unwind works but hides UB.
let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    let r: InterpResult<'tcx, ()> = interp.do_step();
    r.discard_err(); // make the drop well-defined if you truly intend to ignore
}));

Prevention

When it happens

Trigger: Letting an `InterpResult` value fall out of scope without `?`, `match`, `.into()`, or `.discard_err()`. Concrete shapes: `ecx.read_scalar(...);` (statement-discarded), `let _ = ecx.mplace_access(...);`, returning from a function that forgets to propagate an interp result, or storing an `InterpResult` in a field that is later dropped instead of matched.

Common situations: Refactoring an interpreter intrinsic/shim and forgetting a `?`; writing a new Miri foreign-item hook whose body drops the result of an inner call; cargo build of rustc itself after a `InterpErrorInfo` refactor; new contributors to const-eval who treat `InterpResult` like a plain `Result` and call `.ok()`.

Related errors


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