{"id":"c3bce49a265f8fb1","repo":"rust-lang/rust","slug":"no-sub-expr-expected-for","errorCode":null,"errorMessage":"no sub-expr expected for {:?}","messagePattern":"no sub-expr expected for (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_middle/src/hir/mod.rs","lineNumber":299,"sourceCode":"                    | ExprKind::Block(_, _)\n                    | ExprKind::AssignOp(_, _, _)\n                    | ExprKind::Index(_, _, _)\n                    | ExprKind::Break(_, _)\n                    | ExprKind::Ret(_)\n                    | ExprKind::Become(_)\n                    | ExprKind::InlineAsm(_)\n                    | ExprKind::Struct(_, _, _)\n                    | ExprKind::Repeat(_, _)\n                    | ExprKind::Yield(_, _) => true,\n\n                    // These expressions have no (direct) sub-exprs.\n                    ExprKind::ConstBlock(_)\n                    | ExprKind::Loop(_, _, _, _)\n                    | ExprKind::Lit(_)\n                    | ExprKind::Path(_)\n                    | ExprKind::Continue(_)\n                    | ExprKind::OffsetOf(_, _)\n                    | ExprKind::Err(_) => unreachable!(\"no sub-expr expected for {:?}\", expr.kind),\n                }\n            }\n\n            // If we have a subpattern that performs a read, we want to consider this\n            // to diverge for compatibility to support something like `let x: () = *never_ptr;`.\n            Node::LetStmt(LetStmt { init: Some(target), pat, .. }) => {\n                assert_eq!(target.hir_id, expr.hir_id);\n                pat.is_guaranteed_to_constitute_read_for_never()\n            }\n\n            // These nodes (if they have a sub-expr) do constitute a read.\n            Node::Block(_)\n            | Node::Arm(_)\n            | Node::ExprField(_)\n            | Node::AnonConst(_)\n            | Node::ConstBlock(_)\n            | Node::ConstArg(_)\n            | Node::Stmt(_)","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_middle/src/hir/mod.rs#L281-L317","documentation":"unreachable! in expr_guaranteed_to_constitute_read_for_never (compiler/rustc_middle/src/hir/mod.rs:299). When walking a place-expression child of a parent Expr, the match covers every ExprKind that can have a value-producing sub-expression; the leaf kinds (ConstBlock, Loop, Lit, Path, Continue, OffsetOf, Err) are listed as unreachable because they have no direct sub-exprs. Hitting this means the HIR contained an Expr child under one of those leaf kinds, which the compiler considers malformed.","triggerScenarios":"An Expr node whose kind is one of the listed leaf variants unexpectedly has a child expression passed to expr_guaranteed_to_constitute_read_for_never. Caused by malformed HIR from a parser/recovery bug, a proc-macro that synthesized an inconsistent Expr tree, or a refactor adding a new sub-expr to a leaf kind without updating this match.","commonSituations":"Nightly-only features or proc-macros that build unusual Expr shapes; changes to the never-type/`!` coercion logic; recovery after a syntax error producing an ExprKind::Err with children.","solutions":["Report as a rustc ICE with the ExprKind shown in the message and the source span.","Bisect across nightly versions to find the change that introduced the unexpected sub-expression (likely a parser or HIR refactor).","If you write proc-macros, ensure generated Expr nodes do not attach child Exprs to leaf kinds like Lit/Path/Loop."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// Before requesting a sub-expression, verify the parent\n// expression kind actually carries one.\nuse rustc_hir::{Expr, ExprKind, HirId};\nuse rustc_middle::ty::TyCtxt;\n\nfn has_expected_sub_expr(expr: &Expr<'_>) -> bool {\n    matches!(\n        expr.kind,\n        ExprKind::Binary(..)\n            | ExprKind::Assign(..)\n            | ExprKind::AssignOp(..)\n            | ExprKind::Call(..)\n            | ExprKind::MethodCall(..)\n            | ExprKind::Match(..)\n    )\n}","typeGuard":"// Narrow an Expr to one that is safe to descend into for a\n// sub-expression.\nuse rustc_hir::{Expr, ExprKind};\n\nfn expr_with_sub_expr<'a>(expr: &'a Expr<'a>) -> Option<&'a Expr<'a>> {\n    match expr.kind {\n        ExprKind::Binary(_, lhs, _) => Some(lhs),\n        ExprKind::Assign(lhs, _, _) => Some(lhs),\n        ExprKind::Call(callee, _) => Some(callee),\n        ExprKind::Match(scrut, _, _) => Some(scrut),\n        _ => None, // kinds with no sub-expr => do not descend\n    }\n}","tryCatchPattern":null,"preventionTips":["Never call next_sub_expr / sub_expr iteration on an ExprKind you have not matched first","Handle every ExprKind variant in your visitor, returning early for leaf kinds like Lit, Path, ConstBlock","Write exhaustive match arms (and rely on the compiler's non-exhaustive warnings) rather than a default arm that descends blindly"],"tags":["rustc","hir","never-type","unreachable","ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}