rust-lang/rust · error
{:?} shouldn't exist here
Error message
{:?} shouldn't exist here What it means
This `panic!` fires when `lower_expr_inner` encounters an `ExprKind::MacCall` — a yet-to-be-expanded macro invocation. Macro expansion runs in a prior pass (`rustc_expand`), and by the time lowering runs the AST should contain zero `MacCall` nodes. Their presence means macro expansion was incomplete, was skipped, or a procedural macro re-injected an unexpanded `MacCall` into the AST. It is an ICE pointing at the span of the offending macro call.
Source
Thrown at compiler/rustc_ast_lowering/src/expr.rs:500
ty.as_ref().map(|ty| {
self.lower_ty_alloc(
ty,
ImplTraitContext::Disallowed(ImplTraitPosition::Cast),
)
}),
),
ExprKind::Dummy => {
span_bug!(e.span, "lowered ExprKind::Dummy")
}
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
ExprKind::Paren(_) | ExprKind::ForLoop { .. } | ExprKind::Closure(..) => {
unreachable!("already handled")
}
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
ExprKind::DirectConstArg(expr) => {
let e = self.emit_bad_direct_const_arg(e.span, expr, "expression");
hir::ExprKind::Err(e)
}
};
hir::Expr { hir_id: expr_hir_id, kind, span }
})
}
pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
self.with_new_scopes(c.value.span, |this| {
let def_id = this.local_def_id(c.id);
let hir_id = this.lower_node_id(c.id);
let (body, _) = this.with_move_expr_bindings(None, |this| {
this.lower_const_body(c.value.span, Some(&c.value))
});View on GitHub (pinned to 22057b88b0)
Solutions
- As an end user: report the ICE with the proc-macro and invocation that triggered it.
- As a proc-macro author: ensure your macro emits fully-formed expressions (use `quote!` to produce concrete syntax, not nested unexpanded `MacCall` nodes); verify with `cargo expand` that no residual macro calls remain.
- Check for conflicting proc-macro versions where a re-expanded token stream reintroduces a macro call into expr position.
- If developing rustc: verify the expand→lower pipeline re-runs expansion over macro-generated output (expansion recursion depth).
Example fix
// before — proc-macro returns a nested unexpanded macro call as an expression
quote! { some_unexpanded_macro!(args) }
// after — emit concrete expression syntax
quote! { { /* concrete code */ } } Defensive patterns
Strategy: fallback
Validate before calling
// "{:?} shouldn't exist here" is a lowering assertion that a given expr
// kind must not reach this point. No pre-API validation exists; defense is
// to identify and rewrite the offending expression kind.
//
// Approach:
// 1. Run `cargo build` and read the span in the ICE.
// 2. Replace the flagged expr with a standard form (e.g. swap a complex
// match/const-block for a plain `if`/`let`).
// 3. Re-run; if it persists, reduce the crate to the minimal node. Prevention
- Identify the expression kind at the reported span and rewrite it in a more standard form
- Avoid bleeding-edge expr forms (e.g. experimental const/inline blocks) in stable code paths
- Bisect commits to isolate which syntax introduced the unreachable node
- File an ICE with the minimized crate; this indicates a compiler bug, not misuse
When it happens
Trigger: Triggered when the lowering visitor reaches any node with `ExprKind::MacCall(_)` at expr.rs:500. This happens if `rustc_expand` was not run, if a proc-macro returned tokens that re-formed a `MacCall` AST node, or if an earlier expansion produced a residual unexpanded macro in expression position.
Common situations: Encountered by proc-macro authors whose macro returns `expr!unexpanded_macro!(...)`-shaped output, by nightly users after a regression in the expansion-to-lowering handoff, or in partially-compiled crates where a build script skipped expansion. Also seen with attribute macros that splice in token streams containing fresh macro invocations that then never get re-expanded.
Related errors
- shouldn't exist here
- must contain self type as `SelfTy` propagation kind is speci
- arg must exist for infer
- non-`async`/`gen` closure body turned `async`/`gen` during l
- already handled
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/b907e247c285b7ac.json.
Report an issue: GitHub.