{"id":"beadf76429b1870d","repo":"rust-lang/rust","slug":"no-sub-expr-expected-for-parent-node","errorCode":null,"errorMessage":"no sub-expr expected for {parent_node:?}","messagePattern":"no sub-expr expected for (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_middle/src/hir/mod.rs","lineNumber":353,"sourceCode":"            | Node::PathSegment(_)\n            | Node::Ty(_)\n            | Node::AssocItemConstraint(_)\n            | Node::TraitRef(_)\n            | Node::PatField(_)\n            | Node::PatExpr(_)\n            | Node::LetStmt(_)\n            | Node::Synthetic\n            | Node::Err(_)\n            | Node::Ctor(_)\n            | Node::Lifetime(_)\n            | Node::GenericParam(_)\n            | Node::Crate(_)\n            | Node::Infer(_)\n            | Node::WherePredicate(_)\n            | Node::PreciseCapturingNonLifetimeArg(_)\n            | Node::ConstArgExprField(_)\n            | Node::OpaqueTy(_) => {\n                unreachable!(\"no sub-expr expected for {parent_node:?}\")\n            }\n        }\n    }\n\n    #[inline]\n    fn hir_owner_parent_impl(self, owner_id: OwnerId) -> HirId {\n        self.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| {\n            let parent_owner_id = self.local_def_id_to_hir_id(parent_def_id).owner;\n            HirId {\n                owner: parent_owner_id,\n                local_id: self\n                    .hir_owner(parent_owner_id.def_id)\n                    .unwrap()\n                    .parenting\n                    .get(&owner_id.def_id)\n                    .copied()\n                    .unwrap_or(ItemLocalId::ZERO),\n            }","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_middle/src/hir/mod.rs#L335-L371","documentation":"unreachable! in the same function expr_guaranteed_to_constitute_read_for_never (compiler/rustc_middle/src/hir/mod.rs:353), but on the parent-node branch. After handling Node::Expr parents, the match falls through to a list of Node variants that cannot legally be the parent of a place-expression child (Param, Item, TraitItem, ImplItem, Variant, Field, PathSegment, Ty, Lifetime, Crate, Infer, WherePredicate, OpaqueTy, etc.). Hitting it means an Expr was found as a direct child of one of those non-expression-bearing nodes.","triggerScenarios":"parent_hir_node(expr.hir_id) returns one of the listed non-expression Node variants while expr is a syntactic place expression. Indicates malformed HIR parenting, e.g. an Expr wrongly parented under an Item or a Ty rather than under a Block/Expr/Stmt.","commonSituations":"Proc-macros or compiler bugs that mis-wire HirId parents; desugaring regressions where the parent pointer is not updated; analysis tools that traverse HIR assuming every Expr is parented under an Expr/Block.","solutions":["Report as a rustc ICE including the parent_node printed in the message and (if possible) the offending span.","Bisect nightlies to locate the HIR-parenting regression.","If authoring proc-macros, ensure emitted Exprs are placed where the HIR visitor expects them (blocks, statement lists, expression positions), not under type/item nodes."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Same class as 237 but for a parent_node. Verify the parent\n// expression kind before expecting a child sub-expression.\nuse rustc_hir::{Expr, ExprKind};\n\nfn parent_node_has_sub_expr(parent: &Expr<'_>) -> bool {\n    !matches!(\n        parent.kind,\n        ExprKind::Lit(_)\n            | ExprKind::Path(_)\n            | ExprKind::ConstBlock(_)\n            | ExprKind::Field(_, _)\n    )\n}","typeGuard":"// Type-guard that narrows a parent Expr to a composite kind\n// before descending into its sub-expression slot.\nuse rustc_hir::{Expr, ExprKind};\n\nenum SubExprSlot<'a> {\n    Lhs(&'a Expr<'a>),\n    Rhs(&'a Expr<'a>),\n    Callee(&'a Expr<'a>),\n    Scrutinee(&'a Expr<'a>),\n}\n\nfn parent_sub_expr_slot<'a>(parent: &'a Expr<'a>) -> Option<SubExprSlot<'a>> {\n    match parent.kind {\n        ExprKind::Binary(_, lhs, rhs) => Some(SubExprSlot::Lhs(lhs)),\n        ExprKind::Assign(lhs, rhs, _) => Some(SubExprSlot::Rhs(rhs)),\n        ExprKind::Call(callee, _) => Some(SubExprSlot::Callee(callee)),\n        ExprKind::Match(scrut, _, _) => Some(SubExprSlot::Scrutinee(scrut)),\n        _ => None,\n    }\n}","tryCatchPattern":null,"preventionTips":["Match on parent_node.kind and only descend when a sub-expression slot provably exists","Treat leaf ExprKinds (Lit, Path, ConstBlock) as terminal in your HIR walker","Add unit tests covering every ExprKind variant for any visitor that calls sub-expr accessors","Avoid relying on parent_node context from macro-generated code, which can carry unexpected shapes"],"tags":["rustc","hir","never-type","unreachable","ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}