{"id":"063a2a2197a2ad98","repo":"rust-lang/rust","slug":"already-handled","errorCode":null,"errorMessage":"already handled","messagePattern":"already handled","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_ast_lowering/src/expr.rs","lineNumber":497,"sourceCode":"                ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(\n                    *kind,\n                    self.lower_expr(expr),\n                    ty.as_ref().map(|ty| {\n                        self.lower_ty_alloc(\n                            ty,\n                            ImplTraitContext::Disallowed(ImplTraitPosition::Cast),\n                        )\n                    }),\n                ),\n\n                ExprKind::Dummy => {\n                    span_bug!(e.span, \"lowered ExprKind::Dummy\")\n                }\n\n                ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),\n\n                ExprKind::Paren(_) | ExprKind::ForLoop { .. } | ExprKind::Closure(..) => {\n                    unreachable!(\"already handled\")\n                }\n\n                ExprKind::MacCall(_) => panic!(\"{:?} shouldn't exist here\", e.span),\n\n                ExprKind::DirectConstArg(expr) => {\n                    let e = self.emit_bad_direct_const_arg(e.span, expr, \"expression\");\n                    hir::ExprKind::Err(e)\n                }\n            };\n\n            hir::Expr { hir_id: expr_hir_id, kind, span }\n        })\n    }\n\n    pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {\n        self.with_new_scopes(c.value.span, |this| {\n            let def_id = this.local_def_id(c.id);\n            let hir_id = this.lower_node_id(c.id);","sourceCodeStart":479,"sourceCodeEnd":515,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_ast_lowering/src/expr.rs#L479-L515","documentation":"This `unreachable!` fires in `lower_expr_inner` when an `ExprKind::Paren`, `ExprKind::ForLoop`, or `ExprKind::Closure` reaches the inner expr-lowering switch. These three node kinds are handled earlier in the pipeline (Paren is stripped, ForLoop and Closure have dedicated lowering paths invoked from `lower_expr`/`lower_expr_mut`), so their presence in `lower_expr_inner` means the earlier dispatch was skipped or the AST was malformed. It indicates a structural bug in lowering, not a user error.","triggerScenarios":"Triggered when `lower_expr_inner` is called directly (bypassing `lower_expr`) on a node whose kind is `Paren`, `ForLoop { .. }`, or `Closure(..)`. Concretely the arm at expr.rs:496-498 catches these three and aborts. Normally `lower_expr`/`lower_expr_mut` route these elsewhere first.","commonSituations":"Almost exclusively hit by rustc developers who added a new call site of `lower_expr_inner` without first unwrapping `Paren` or routing `ForLoop`/`Closure` through their dedicated lower functions. End users on stable virtually never see it; nightly users might if a regression lands. Also reachable via procedural-macro-generated AST that injects raw `Paren`/`Closure` nodes where they aren't expected.","solutions":["If you hit this as a user: report an ICE with the reproducer to https://github.com/rust-lang/rust/issues.","If developing rustc: ensure any new `lower_expr_inner` call site first dispatches `Paren`/`ForLoop`/`Closure` through `lower_expr`/`lower_expr_mut` or strips them.","Audit proc-macro output: if a custom proc-macro synthesizes AST, ensure it doesn't emit bare `Paren`/`Closure` kinds in positions the compiler lowers via `lower_expr_inner`.","Bisect to find the rustc commit that introduced the new (broken) call site."],"exampleFix":"// before — rustc internal: calling lower_expr_inner directly on a Closure node\nlet kind = self.lower_expr_inner(e);\n\n// after — route through lower_expr which dispatches Closure first\nlet kind = self.lower_expr(e);","handlingStrategy":"fallback","validationCode":"// \"already handled\" is an internal lowering invariant — an expression\n// kind reached a branch that asserts it was processed earlier. There is no\n// caller-side API to validate against it; the defense is source-level\n// simplification of the offending expression.\n//\n// Mitigation pattern: factor the expression into named `let` bindings so\n// each sub-expression takes a single, standard lowering path.\n//   // Before: let v = f(g(h(x)));\n//   // After:  let a = h(x); let b = g(a); let v = f(b);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Simplify complex expressions; extract sub-expressions into named `let` bindings","Bisect the file/expr that triggers the ICE and minimize the repro","Try an equivalent but more conventional expression form","Report as an ICE — this path should be unreachable from valid source"],"tags":["rustc","ast-lowering","ice","unreachable"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}