Skip to content

transform: call-inliner stack overflow on pi bundle — inline_calls_in_stmts recursion is unguarded (expr-side cap from #733 never binds) #6593

Description

@proggeramlug

First wall of the pi coding-agent bring-up (tracker #6564): compiling pi's bundle (13.3MB unminified esbuild ESM output of @earendil-works/pi-coding-agent@0.80.10) crashes the compiler:

thread 'perry-main' (…) has overflowed its stack
fatal runtime error: stack overflow, aborting

Reproduces identically at the stock 128MB perry-main stack AND at a 512MB test bump — so this is effectively unbounded recursion, not a merely-deep finite walk.

Symbolicated crash stack (strip=none rebuild, macOS .ips + nm)

The overflow is the call inliner's mutual recursion, entered from module collection:

36-frame captured window (top of a very deep stack), most frequent:
  11x perry_transform::inline::call_inliner::inline_calls_in_expr
   9x perry_transform::inline::call_inliner::inline_calls_in_stmts
   2x perry_transform::inline::call_inliner::stmt_contains_return
   1x perry_transform::inline::inline_functions
   1x perry::commands::compile::collect_modules::collect_module_finish

Root cause

inline_calls_in_expr is guarded (enter_inline_expr_recursion, cap MAX_INLINE_EXPR_RECURSION_DEPTH = 128, added for #733), but inline_calls_in_stmts is not. A stmts→stmts recursion chain (nested blocks / closure bodies / re-walks of freshly inlined bodies) never passes the expr-side guard, so the shared depth budget never binds and the mutual recursion grows without limit on this bundle's AST shapes.

Fix being validated

Mirror the guard at the inline_calls_in_stmts entry, sharing the same thread-local depth budget: on cap, clear exact_receiver_facts and return with the subtree un-inlined (semantics-preserving — the inliner is an optimization pass; identical rationale to the existing expr-side bail). Validation against the pi bundle is running; PR to follow if green.

Repro: secret-tests/pi-target/build-bundle.sh output (shrinkwrap-pinned npm install + esbuild, recipe in tracker #6564) — deterministic input; happy to help minimize to a small fixture if wanted.

Also worth considering upstream (secondary): an env override for the perry-main stack size — the current 128MB constant has now been outgrown twice (v0.5.973 ioredis bump, this).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions