Prerequisites
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 by rfl, decide, whnf
Nat.reduceShiftLeft simproc (src/Lean/Meta/Tactic/Simp/BuiltinSimprocs/Nat.lean): simp
evalShift in src/Lean/Meta/Sym/Simp/EvalGround.lean and src/Lean/Meta/Sym/DSimp/EvalGround.lean (Nat, Int and BitVec shifts): cbv, bv_decide normalization
propagateNatShiftLeft (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.
Prerequisites
https://github.com/leanprover/lean4/issues
Avoid dependencies to Mathlib or Batteries.
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.shiftLefton literals without checking the shift amount. The runtime'slean_nat_shiftlcallslean_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 orlake build).The kernel no longer has this problem: it now refuses such shifts with a kernel exception.
Nat.powis also already protected on the elaborator side bycheckExponent.Nat.shiftLeftis 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):grindNat.shiftLeft(src/Lean/Compiler/LCNF/Simp/ConstantFold.lean): compiling a definitionSteps to Reproduce
Each of the following files, on its own, crashes Lean:
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 onv4.35.0-rc2andv4.32.0-rc1)Linux 6.17.0 aarch64
Additional Information
2 ^ 4294967296does not crash:checkExponentlogs "exponent 4294967296 exceeds the threshold 256" instead. For shifts, the exponentiation threshold would be too restrictive, since evaluating1 <<< 1000is 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 least2^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.