`Nat.shiftLeft` by 2^32 or more crashes Lean in `rfl`, `decide`, `simp`, `cbv`, `grind` and the compiler
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Domain
- compilers
Research direction
Run the minimal reproduction examples first to confirm the panic, then read Lean.Meta.reduceNat? in src/Lean/Meta/WHNF.lean and the listed shift call sites in the simproc, evaluator, Grind, and LCNF constant-folder files. Done means oversized nonzero shifts no longer terminate Lean, while ordinary shifts such as 1 << 1000 still evaluate.
Written by the indexing model from the issue text.
Description
Prerequisites
- Check that your issue is not already filed:
https://github.com/leanprover/lean4/issues - Reduce the issue to a minimal, self-contained, reproducible test case.
Avoid dependencies to Mathlib or Batteries. - Test your test case against the latest nightly release, for example on
https://live.lean-lang.org/#project=lean-nightly
(You can also use the settings there to switch to “Lean nightly”)
Description
Several elaborator and compiler procedures evaluate Nat.shiftLeft on literals without checking the shift amount. The runtime's lean_nat_shiftl calls lean_internal_panic("Nat.shiftl exponent is too big") when the shifted value is nonzero and the shift amount does not fit in 32 bits, so a one-line file terminates the whole Lean process (and with it the language server or lake build).
The kernel no longer has this problem: it now refuses such shifts with a kernel exception. Nat.pow is also already protected on the elaborator side by checkExponent. Nat.shiftLeft is not guarded at these call sites:
Lean.Meta.reduceNat?(src/Lean/Meta/WHNF.lean): reached byrfl,decide,whnfNat.reduceShiftLeftsimproc (src/Lean/Meta/Tactic/Simp/BuiltinSimprocs/Nat.lean):simpevalShiftinsrc/Lean/Meta/Sym/Simp/EvalGround.leanandsrc/Lean/Meta/Sym/DSimp/EvalGround.lean(Nat,IntandBitVecshifts):cbv,bv_decidenormalizationpropagateNatShiftLeft(src/Lean/Meta/Tactic/Grind/Arith/Propagate.lean):grind- the LCNF constant folder for
Nat.shiftLeft(src/Lean/Compiler/LCNF/Simp/ConstantFold.lean): compiling a definition
Steps to Reproduce
Each of the following files, on its own, crashes Lean:
example : (1 <<< 4294967296 : Nat) = 0 := by rfl
example : (1 <<< 4294967296 : Nat) = 0 := by decide
example : (1 <<< 4294967296 : Nat) = 0 := by simp
example : (1 <<< 4294967296 : Nat) = 0 := by cbv
example : ((1 : Int) <<< (4294967296 : Nat)) = 0 := by cbv
example : ((1#8) <<< (4294967296 : Nat)) = 0#8 := by cbv
example (x : Nat) (h : x = 4294967296) : (1 <<< x : Nat) = 0 := by grind
def f : Nat := 1 <<< 4294967296
Expected behavior: The shift is left unevaluated (or an error or warning is reported, as for 2 ^ 4294967296), and Lean keeps running.
Actual behavior: The process exits with INTERNAL PANIC: Nat.shiftl exponent is too big.
Versions
4.36.0-nightly-2026-09-16 (also reproduced on v4.35.0-rc2 and v4.32.0-rc1)
Linux 6.17.0 aarch64
Additional Information
2 ^ 4294967296 does not crash: checkExponent logs "exponent 4294967296 exceeds the threshold 256" instead. For shifts, the exponentiation threshold would be too restrictive, since evaluating 1 <<< 1000 is cheap and works today. The runtime's actual limit is the one that matters: skip evaluation when the value is nonzero and the shift amount is at least 2^32.
I plan to open a PR implementing that guard at the call sites above. An AI assistant (Claude) found and reduced this bug and drafted this report; each reproduction above was run on the listed versions.
Impact
Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.
- Dominant language
- Lean
- Stars
- 9.2k
- Forks
- 990
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 175
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from leanprover/lean4
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
leanprover/lean4#15197 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
leanprover/lean4#15172 · 1 comment ·
-
P-medium
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
leanprover/lean4#15037 ·
-
`Nat.lt` docstring OpenP-low
Difficulty 1/5 Under an hour Newbie friendliness 85/100
leanprover/lean4#15014 ·
-
P-medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
leanprover/lean4#14973 · 1 comment ·
All issues in leanprover/lean4
Similar issues
-
mlir
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
llvm/llvm-project#224908 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
area-CodeGen-coreclr untriaged
Difficulty 1/5 Under an hour Newbie friendliness 92/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
secondlife/sl-vscode-plugin#147 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
objectionary/phie#149 ·