rust-lang/rust · critical

Not a HIR owner

Error message

Not a HIR owner

What it means

Panic in ProjectedMaybeOwner::unwrap (compiler/rustc_middle/src/hir/mod.rs:448). The method calls as_owner() (returns Some only for ProjectedMaybeOwner::Owner) and otherwise panics with 'Not a HIR owner'. It is the checked accessor for the Owner variant; callers use it when they have already established that the value represents an owning node, and a NonOwner value is a contract violation.

Source

Thrown at compiler/rustc_middle/src/hir/mod.rs:448

            MaybeOwner::Owner(o) => ProjectedMaybeOwner::Owner(ProjectedOwnerInfo {
                nodes: &o.nodes,
                parenting: &o.parenting,
                trait_map: &o.trait_map,
                delayed_lints: &o.delayed_lints,
            }),
            MaybeOwner::NonOwner(hir_id) => ProjectedMaybeOwner::NonOwner(hir_id),
        }
    }

    pub fn as_owner(&self) -> Option<&ProjectedOwnerInfo<'tcx>> {
        match self {
            ProjectedMaybeOwner::Owner(i) => Some(i),
            ProjectedMaybeOwner::NonOwner(_) => None,
        }
    }

    pub fn unwrap(&'tcx self) -> &'tcx ProjectedOwnerInfo<'tcx> {
        self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner"))
    }
}

pub fn provide(providers: &mut Providers) {
    providers.hir_crate_items = map::hir_crate_items;
    providers.crate_hash = map::crate_hash;
    providers.hir_module_items = map::hir_module_items;
    providers.hir_attr_map =
        |tcx, id| tcx.lower_to_hir(id).as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs);
    providers.hir_owner = |tcx, def_id| ProjectedMaybeOwner::new(tcx.lower_to_hir(def_id));
    providers.hir_owner_parent_q = |tcx, owner_id| tcx.hir_owner_parent_impl(owner_id);
    providers.def_span = |tcx, def_id| tcx.hir_span(tcx.local_def_id_to_hir_id(def_id));
    providers.def_ident_span = |tcx, def_id| {
        let hir_id = tcx.local_def_id_to_hir_id(def_id);
        tcx.hir_opt_ident_span(hir_id)
    };
    providers.ty_span = |tcx, def_id| {
        let node = tcx.hir_node_by_def_id(def_id);

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Use as_owner() / match on ProjectedMaybeOwner::Owner vs NonOwner before unwrapping.
  2. Confirm the def_id you pass actually owns HIR (items, fn/trait/impl bodies that are owners); for non-owners use the parent owner.
  3. If reached during normal compilation, report as an ICE with the owner_id/def_id context.

Example fix

// before
let owner = tcx.hir_owner(def_id).unwrap();

// after
match tcx.hir_owner(def_id) {
    ProjectedMaybeOwner::Owner(o) => { /* use o */ }
    ProjectedMaybeOwner::NonOwner(hir_id) => { /* handle non-owner */ }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Before calling an API that requires a HIR owner, verify the
// DefId/HirId actually resolves to an owner.
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::TyCtxt;

fn is_hir_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
    // hir_owner_nodes returns None for non-owner items
    tcx.hir_owner_nodes(def_id).is_some()
}

Type guard

// Narrow a LocalDefId to a confirmed HIR owner before
// invoking owner-scoped queries.
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;

fn as_hir_owner<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: LocalDefId,
) -> Option<LocalDefId> {
    tcx.hir_owner_nodes(def_id)
        .map(|_| def_id)
        // or, if using the older API:
        .or_else(|| {
            let map = tcx.hir();
            map.opt_local_def_id_to_hir_id(def_id)
                .filter(|hid| map.is_owner(*hid))
                .map(|_| def_id)
        })
}

Prevention

When it happens

Trigger: Calling .unwrap() on a ProjectedMaybeOwner (produced by ProjectedMaybeOwner::new(tcx.lower_to_hir(def_id))) when the def_id is a non-owner (e.g. an associated item, a nested item, or anything whose HIR is embedded in a parent owner rather than being an owner itself). The underlying lower_to_hir returned MaybeOwner::NonOwner(hir_id).

Common situations: Compiler passes or tools that assume every def_id is an owner; mismatch after HIR owner reclassification (e.g. moving an item from owner to nested); calling providers.hir_owner(...).unwrap() on a non-owner def_id.

Related errors


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