rust-lang/rust · critical

This method is not called in free functions, as patterns are

Error message

This method is not called in free functions, as patterns are always allowed there

What it means

Internal `unreachable!` in `recover_arg_parse`, which recovers from malformed function parameters by re-parsing `pat: Ty`. This recovery is only valid for trait method signatures and function-pointer types, where identifier-only parameters (no pattern) are disallowed; for free functions and inherent impls patterns are always permitted, so the caller must never pass `FnContext::Free` or `FnContext::Impl`. The `target` field's match arms for those two variants panic.

Source

Thrown at compiler/rustc_parse/src/parser/diagnostics.rs:2400

            return if self.token == token::Lt { None } else { Some(ident) };
        }
        None
    }

    #[cold]
    pub(super) fn recover_arg_parse(
        &mut self,
        context: FnContext,
    ) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
        let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
        self.expect(exp!(Colon))?;
        let ty = self.parse_ty()?;
        self.dcx().emit_err(PatternMethodParamWithoutBody {
            span: pat.span,
            target: match context {
                FnContext::Trait => "methods without bodies",
                FnContext::FunctionPtrType => "function pointer types",
                FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"),
                FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"),
            },
        });

        // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
        let pat = Box::new(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID });
        Ok((pat, ty))
    }

    pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
        let span = param.pat.span;
        let guar = self.dcx().emit_err(SelfParamNotFirst { span });
        param.ty.kind = TyKind::Err(guar);
        Ok(param)
    }

    pub(super) fn consume_block(
        &mut self,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Fix the syntax error the compiler was attempting to recover from (add the missing type annotation) so recovery is not invoked
  2. Report as a rustc ICE with the malformed function signature and the backtrace
  3. Try a different toolchain to check whether it is a recent regression

Example fix

// before: malformed parameter triggers recovery
fn f(x) {}
// after: provide the parameter type so recovery is unnecessary
fn f(x: i32) {}
Defensive patterns

Strategy: type-guard

Type guard

use rustc_ast::ast::{Item, ItemKind};
pub fn item_allows_patterns_unconditionally(item: &Item) -> bool {
    // Free functions always allow patterns; the guarded method is meant for
    // closures/associated fns/other contexts where patterns may be restricted.
    matches!(item.kind, ItemKind::Fn(..)) && !item_is_in_impl_or_trait(item)
}
fn item_is_in_impl_or_trait(_item: &Item) -> bool { /* consult parent context */ false }

Prevention

When it happens

Trigger: The parser's argument-recovery logic is invoked with `context = FnContext::Free` or `FnContext::Impl`, i.e. the caller misclassified the surrounding function kind while recovering from a bad parameter.

Common situations: Compiler regression in parameter parsing/recovery after refactor of `FnContext`; surfaced when a user writes a malformed parameter (e.g. missing type) and the recovery path is misrouted.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/c8ca520080bd621c.json. Report an issue: GitHub.