Skip to content

fix: do not evaluate Nat left shifts the runtime cannot perform - #15194

Draft
gersh wants to merge 1 commit into
leanprover:masterfrom
gersh:fix-nat-shiftleft-panic
Draft

gersh wants to merge 1 commit into
leanprover:masterfrom
gersh:fix-nat-shiftleft-panic

Conversation

@gersh

@gersh gersh commented Sep 17, 2026

Copy link
Copy Markdown

This PR stops elaboration-time and compile-time evaluation of Nat left shifts whose shift amount does not fit in 32 bits, so they no longer abort the Lean process with "Nat.shiftl exponent is too big".

The runtime's lean_nat_shiftl calls lean_internal_panic when the shifted value is nonzero and the shift amount is at least 2^32. The kernel already refuses such shifts with a kernel exception, and Nat.pow is protected on the elaborator side by checkExponent, but several procedures evaluated <<< on literals unconditionally. A new predicate, Lean.canEvalNatShiftLeft a b (a = 0 ∨ b < UInt32.size), is now checked before evaluating a left shift in:

  • Meta.reduceNat? (whnf, rfl, decide)
  • the Nat.reduceShiftLeft, Fin.reduceShiftLeft, BitVec.reduceShiftLeft, BitVec.reduceHShiftLeft and BitVec.reduceShiftLeftZeroExtend simprocs
  • Sym ground evaluation of shifts on Nat, Int, Fin and BitVec and of BitVec.shiftLeft/shiftLeftZeroExtend (cbv, bv_decide normalization)
  • the grind propagators for Nat and BitVec left shifts
  • the LCNF constant folder for Nat.shiftLeft

When the predicate fails, the shift is left unevaluated, so the affected tactics report an ordinary failure (for cbv, which then unfolds Nat.shiftLeft, "maximum recursion depth has been reached"). Shifts the runtime can evaluate are unaffected; unlike checkExponent, no size threshold is introduced.

Closes #15193

AI assistance: the bug was found with, and this change and its tests were drafted with, an AI assistant (Claude). The new test and the full stage1 test suite (4219 tests) pass on a local build of this branch (aarch64 Linux).

🤖 Generated with Claude Code

Elaboration- and compile-time evaluation of `a <<< b` on literals called the
runtime `Nat.shiftLeft`, which aborts the process when `a ≠ 0` and `b` does not
fit in 32 bits. Check the new `canEvalNatShiftLeft` before evaluating in
`Meta.reduceNat?`, the `Nat`/`Fin`/`BitVec` shift simprocs, `Sym` ground
evaluation, the `grind` shift propagators and the LCNF constant folder.

Closes leanprover#15193

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nat.shiftLeft by 2^32 or more crashes Lean in rfl, decide, simp, cbv, grind and the compiler

1 participant