rust-lang/rust · critical

variant_with_id: unknown variant

Error message

variant_with_id: unknown variant

What it means

This `expect` in adt.rs:598 (`variant_with_id`) fires when `AdtDef::variants()` does not contain a `VariantDef` whose `def_id` equals the queried `vid`. The ADT's variant list is built once during HIR lowering/TyCtxt construction; a lookup miss indicates a stale or mismatched DefId was handed to the ADT — an internal consistency bug, normally not reachable from valid user code. Sibling lookups (`variant_with_ctor_id`, `variant_index_with_id`) share the same invariant.

Source

Thrown at compiler/rustc_middle/src/ty/adt.rs:598

        // This would disallow the following kind of enum from being casted into integer.
        // ```
        // enum Enum {
        //    Foo() = 1,
        //    Bar{} = 2,
        //    Baz = 3,
        // }
        // ```
        if self.variants().iter().any(|v| {
            matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind() != Some(CtorKind::Const)
        }) {
            return false;
        }
        self.variants().iter().all(|v| v.fields.is_empty())
    }

    /// Return a `VariantDef` given a variant id.
    pub fn variant_with_id(self, vid: DefId) -> &'tcx VariantDef {
        self.variants().iter().find(|v| v.def_id == vid).expect("variant_with_id: unknown variant")
    }

    /// Return a `VariantDef` given a constructor id.
    pub fn variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef {
        self.variants()
            .iter()
            .find(|v| v.ctor_def_id() == Some(cid))
            .expect("variant_with_ctor_id: unknown variant")
    }

    /// Return the index of `VariantDef` given a variant id.
    #[inline]
    pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx {
        self.variants()
            .iter_enumerated()
            .find(|(_, v)| v.def_id == vid)
            .expect("variant_index_with_id: unknown variant")
            .0

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Run `cargo clean` and rebuild to rule out incremental-cache desync.
  2. Pin or upgrade the toolchain to a known-good nightly (the ICE is usually fixed quickly once reported).
  3. Reduce the failing crate and file an ICE report at https://github.com/rust-lang/rust with the backtrace and `RUST_BACKTRACE=full` output.
  4. If a proc-macro is involved, check that it emits fresh spans/DefIds rather than caching them across compilations.
Defensive patterns

Strategy: retry

Validate before calling

// variant_with_id failures almost always mean stale/corrupt rmeta for an enum variant.
// Validate the build artifacts are fresh before trusting any ADT variant index.
fn build_artifacts_fresh(meta_stamp: std::time::SystemTime, src_stamp: std::time::SystemTime) -> bool {
    meta_stamp > src_stamp // metadata newer than source -> safe to trust variant ids
}

Type guard

// Confirm a variant still exists in the *current* metadata before indexing by id.
fn variant_exists<E: EnumProbe>(id: u32) -> bool {
    E::variant_count() > id
}

Prevention

When it happens

Trigger: Called when the compiler resolves `Res::Def(DefKind::Variant, vid)` via `variant_of_res` (adt.rs:628) or directly via `tcx.adt_def(..).variant_with_id(did)`, but `did` is not a variant of that ADT — e.g. a DefId from a different enum passed in due to an incremental-compilation cache desync or a HIR query ordering bug.

Common situations: Incremental compilation (`-C incremental`) corruption after a compiler upgrade; proc-macro or macro_rules that synthesizes enum variant references; rename/refactor of an enum variant leaving a stale DefId in a cached query; enum variants generated by a derive macro whose input changed.

Related errors


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