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
- Use as_owner() / match on ProjectedMaybeOwner::Owner vs NonOwner before unwrapping.
- Confirm the def_id you pass actually owns HIR (items, fn/trait/impl bodies that are owners); for non-owners use the parent owner.
- 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
- Always check tcx.hir_owner_nodes(def_id).is_some() before calling owner-scoped HIR queries
- Do not assume a DefId from a foreign crate resolves to a local HIR owner; cross-crate items lack local HIR
- For inline or synthetic DefIds generated by macros, verify ownership before traversal
- Prefer LocalDefId over HirId for owner-scoped APIs to make the ownership requirement explicit at the type level
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
- not a module: {node:?}
- processing delegation
- no sub-expr expected for {:?}
- no sub-expr expected for {parent_node:?}
- unsupported integer: {self:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/44d053b696ff49b1.json.
Report an issue: GitHub.