rust-lang/rust · critical

trying to decode `DefIndex` outside the context of a `DefId`

Error message

trying to decode `DefIndex` outside the context of a `DefId`

What it means

`CacheDecoder::decode_def_index` (on_disk_cache.rs:693) is a deliberate, unconditional `panic!("trying to decode DefIndex outside the context of a DefId")`. A bare `DefIndex` is only meaningful relative to a specific `CrateNum`, and both can change between sessions, so the cache encodes `DefId`s as `DefPathHash` and re-maps them on load. Decoding a raw `DefIndex` is therefore ambiguous and always rejected. Reaching it means some type persisted a standalone `DefIndex` instead of wrapping it in a `DefId`.

Source

Thrown at compiler/rustc_middle/src/query/on_disk_cache.rs:693

            |this| Symbol::intern(this.read_str()),
            |opaque| Symbol::intern(opaque.read_str()),
        )
    }

    fn decode_byte_symbol(&mut self) -> ByteSymbol {
        self.decode_symbol_or_byte_symbol(
            ByteSymbol::new,
            |this| ByteSymbol::intern(this.read_byte_str()),
            |opaque| ByteSymbol::intern(opaque.read_byte_str()),
        )
    }

    // This impl makes sure that we get a runtime error when we try decode a
    // `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
    // because we would not know how to transform the `DefIndex` to the current
    // context.
    fn decode_def_index(&mut self) -> DefIndex {
        panic!("trying to decode `DefIndex` outside the context of a `DefId`")
    }
}

impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx UnordSet<LocalDefId> {
    #[inline]
    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
        RefDecodable::decode(d)
    }
}

impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
    for &'tcx UnordMap<DefId, ty::EarlyBinder<'tcx, Ty<'tcx>>>
{
    #[inline]
    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
        RefDecodable::decode(d)
    }
}

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Report to rust-lang/rust with the failing crate and `rustc -vV`; the persisted type should store a `DefId` (decoded via `DefPathHash`), not a bare `DefIndex`.
  2. In-tree fix: change the offending field to `DefId` (or `LocalDefId`/`DefPathHash`) so the decoder re-maps it across sessions.
  3. If deriving `Decodable`, audit every field for `DefIndex` and replace or wrap it; re-run `x.py test compiler/rustc_middle`.
  4. As a quick verification, grep `compiler/` for `DefIndex` inside any struct whose impl list includes `Decodable<CacheDecoder>`.

Example fix

// before — bare DefIndex persisted (panics on decode)
#[derive(Encodable, Decodable)]
struct CachedItemRef {
    index: DefIndex, // ambiguous across sessions
}

// after — store a DefId, which the cache decodes via DefPathHash
#[derive(Encodable, Decodable)]
struct CachedItemRef {
    def_id: DefId, // re-mapped correctly on load
}
Defensive patterns

Strategy: fallback

Try / catch

// Decoding a DefIndex outside a DefId context means the cache's DefIndex->DefPathHash
// table is missing or stale. No caller-side pre-check exists; fall back to a clean build.
use std::process::Command;
fn build_clean_fallback(dir: &str) -> std::io::Result<std::process::ExitStatus> {
    let s = Command::new("cargo").args(["build"]).current_dir(dir).status()?;
    if s.success() { return Ok(s); }
    let _ = Command::new("cargo").args(["clean"]).current_dir(dir).status();
    Command::new("cargo").arg("build").current_dir(dir).status()
}

Prevention

When it happens

Trigger: Triggered when a type containing a bare `DefIndex` field (rather than a `DefId`) is `derive`d as `Decodable<CacheDecoder>` and that type appears in a query result written to the incremental cache; the derived impl calls `decode_def_index`, which panics unconditionally.

Common situations: Encountered by rustc contributors and tooling authors who add a new persisted type and inadvertently include a `DefIndex` (e.g. a `LocalDefFileIndex`-like helper, or a copy of a `DefId`'s index field) without converting it to a `DefId`/`DefPathHash`. End users of released rustc never see it; if they do, it's a compiler regression to report.

Related errors


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