rust-lang/rust · critical
not a module: {node:?}
Error message
not a module: {node:?} What it means
Panic in hir_get_module (compiler/rustc_middle/src/hir/map.rs:420). Given a LocalModId, it constructs the owner HirId and expects hir_owner_node to return an OwnerNode::Item of ItemKind::Mod, or OwnerNode::Crate. Any other node shape triggers this, meaning the LocalModId did not refer to an actual module/crate owner.
Source
Thrown at compiler/rustc_middle/src/hir/map.rs:420
}
/// Gets the attributes on the crate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter
/// dep-graph access.
pub fn hir_krate_attrs(self) -> &'tcx [Attribute] {
self.hir_attrs(CRATE_HIR_ID)
}
pub fn hir_rustc_coherence_is_core(self) -> bool {
find_attr!(self.hir_krate_attrs(), RustcCoherenceIsCore)
}
pub fn hir_get_module(self, module: LocalModId) -> (&'tcx Mod<'tcx>, Span, HirId) {
let hir_id = HirId::make_owner(module.to_local_def_id());
match self.hir_owner_node(hir_id.owner) {
OwnerNode::Item(&Item { span, kind: ItemKind::Mod(_, m), .. }) => (m, span, hir_id),
OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id),
node => panic!("not a module: {node:?}"),
}
}
/// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`.
pub fn hir_walk_toplevel_module<V>(self, visitor: &mut V) -> V::Result
where
V: Visitor<'tcx>,
{
let (top_mod, span, hir_id) = self.hir_get_module(CRATE_MOD_ID);
visitor.visit_mod(top_mod, span, hir_id)
}
/// Walks the attributes in a crate.
pub fn hir_walk_attributes<V>(self, visitor: &mut V) -> V::Result
where
V: Visitor<'tcx>,
{
let krate = self.hir_crate_items(());View on GitHub (pinned to 22057b88b0)
Solutions
- If this is your own tool/lint, validate that the LocalModId you pass actually points at a mod owner before calling hir_get_module.
- Report as a rustc ICE if reached through normal compilation — include the node printed in the message.
- Try a clean build or a different nightly to rule out a stale incremental cache holding a bad HIR.
Defensive patterns
Strategy: type-guard
Validate before calling
// Before treating a HirId as a module, confirm the HIR node kind
// is actually a module item.
use rustc_hir::{HirId, Node, Item, ItemKind};
use rustc_middle::ty::TyCtxt;
fn hir_node_is_module(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
matches!(
tcx.hir().get(hir_id),
Node::Item(Item { kind: ItemKind::Mod(..), .. })
)
} Type guard
// Narrow a HirId to a known-module node before calling
// module-specific HIR map methods.
use rustc_hir::{HirId, Node, Item, ItemKind};
use rustc_middle::ty::TyCtxt;
fn as_module_owner<'tcx>(
tcx: TyCtxt<'tcx>,
hir_id: HirId,
) -> Option<&'tcx Item<'tcx>> {
if let Node::Item(item) = tcx.hir().get(hir_id) {
if matches!(item.kind, ItemKind::Mod(..)) {
return Some(item);
}
}
None
} Prevention
- Always check tcx.hir().get(hir_id) against Node::Item with ItemKind::Mod before calling module-only APIs
- Do not assume a DefId maps to a module just because it appears in a path segment
- When walking HIR from a macro-generated node, verify the kind at every hop rather than skipping checks
When it happens
Trigger: Calling tcx.hir_get_module(id) with a LocalModId whose owning def is not a mod item (e.g. a block expression, an inline module whose owner is a function, or an out-of-range/corrupted LocalModId). Happens inside rustc passes or custom lints/tools that walk module trees.
Common situations: Compiler-internal bug where a non-module owner is registered in the module map; procedural macros or third-party analysis tools that synthesize or pass through HirId/LocalModId values incorrectly; mismatch after a HIR refactor.
Related errors
- processing delegation
- no sub-expr expected for {:?}
- no sub-expr expected for {parent_node:?}
- Not a HIR owner
- unsupported integer: {self:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/0cbf496d18cf4f32.json.
Report an issue: GitHub.