You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bc: suppress try_depth around speculative compile-time fold prim call
try_fold_call and try_fold_arg invoke pure prims speculatively at
compile time to test whether a (head literal-args...) call can fold
to a constant. The contract assumes prim_throw_classified will take
the "set diag and return NULL" branch so the caller can clear_error
and decline. That branch only runs when try_depth == 0; with an
active try-frame in the surrounding eval context, the prim longjmps
into the user's catch instead, escaping the compile entirely.
Reproducer: (defn f [] (if (zero? 0) 43 (quot 1 0))) (f). The
constant-condition fold doesn't fire because (zero? 0) is a cons
(not self-evaluating), so both branches compile. The speculative
fold of (quot 1 0) raises and longjmps; the user sees a runtime
quot: division by zero error from an unreachable else-branch.
Fix: save and zero try_depth around the speculative prim call in
both try_fold_call and try_fold_arg. The prim sees a clean no-try
context, takes the diag-return-NULL path, and the existing
clear_error + decline logic works as documented. try_stack
contents stay untouched; only the depth counter is temporarily
masked. tests/bc_let_fold_test.clj gains
if-else-fold-error-stays-unreachable covering the anchor
reproducer plus mod / rem / when-with-quot / param-driven cond.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments