Zulip Chat Archive
Stream: lean4
Topic: maxRecDepth on simp [reduceOfInt]
Tobias Grosser (Dec 27 2024 at 21:49):
The following simp call fails for me:
-- set_option maxRecDepth 1600
theorem test2 (e : (BitVec 1023)) :
some 0#1023 =
if (BitVec.ofInt 1023 (-70368744177664) &&& 70368040490200#1023 != 0)
then none else none := by
/-
tactic 'simp' failed, nested error:
maximum recursion depth has been reached
use `set_option maxRecDepth <num>` to increase limit
use `set_option diagnostics true` to get diagnostic information
-/
simp only [BitVec.reduceOfInt]
Tobias Grosser (Dec 27 2024 at 21:50):
and can be fixed with a sufficiently large maxRecDepth of 1600.
Tobias Grosser (Dec 27 2024 at 21:50):
AFAIU this should not happen.
Tobias Grosser (Dec 27 2024 at 21:50):
[reduction] unfolded declarations (max: 1536, num: 2): ▼
[] Nat.rec ↦ 1536
[] Nat.pow ↦ 1534
[reduction] unfolded reducible declarations (max: 1536, num: 1): ▼
[] Nat.casesOn ↦ 1536
Tobias Grosser (Dec 27 2024 at 21:51):
The elaboration time with maxRecDepth increased is fast, but setting this globally triggers timeouts in other parts of my project.
Tobias Grosser (Dec 27 2024 at 21:51):
Any ideas how to debug this best?
Henrik Böving (Dec 27 2024 at 21:58):
With
theorem test2 (e : (BitVec 1023)) :
some 0#1023 =
if (BitVec.ofInt 1023 (-70368744177664) &&& 70368040490200#1023 != 0)
then none else none := by
set_option trace.Meta.Tactic.simp true in
simp (config:={failIfUnchanged := false}) only [BitVec.reduceOfInt]
we get:
[Meta.Tactic.simp.unify] eq_self:1000, failed to unify
?a = ?a
with
(89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944#1023 &&&
70368040490200#1023 !=
0) =
true
[Meta.Tactic.simp.unify] eq_self:1000, failed to unify
?a = ?a
with
(89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944#1023 &&&
70368040490200#1023 !=
0) =
true
eq_self
is one of the simp only builtins
looking at the trace of the unifier:
theorem test2 (e : (BitVec 1023)) :
some 0#1023 =
if (BitVec.ofInt 1023 (-70368744177664) &&& 70368040490200#1023 != 0)
then none else none := by
set_option trace.Meta.isDefEq true in
simp (config:={failIfUnchanged := false}) only [BitVec.reduceOfInt]
there seems to be a query at the end that goes bad:
[Meta.isDefEq] ✅️ if ?b then ?x
else ?y =?= if (BitVec.ofInt 1023 (-70368744177664) &&& 70368040490200#1023 != 0) = true then none else none ▶
[Meta.isDefEq] ❌️ ?a =
?a =?= (89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944#1023 &&&
70368040490200#1023 !=
0) =
true ▶
[Meta.isDefEq] ❌️ ?a =
?a =?= (89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944#1023 &&&
70368040490200#1023 !=
0) =
true ▶
[Meta.isDefEq] ✅️ ?c =?= (89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944#1023 &&&
70368040490200#1023 !=
0) =
true ▶
[Meta.isDefEq] 💥️ ?h₁ =?= Eq.refl
((89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944#1023 &&&
70368040490200#1023 !=
0) =
true) ▶
Unfodling this trace it unfolds everything to:
match -70368744177664 % Int.ofNat (2 ^ 1023) with
| Int.ofNat n => n
| Int.negSucc a =>
0 =?= 89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678094443367890944 %
2 ^ 1023
and at this point we are presumably computing 2 ^ 1023
in whnf
and loose.
I'm not quite sure what is creating the ?h
query but it looks similar to the ones that eq_self
is asking for so it's potentially responsible here I guess?
Tobias Grosser (Dec 27 2024 at 22:14):
The same failure arises with:
--set_option maxRecDepth 1600
theorem test2 (e : (BitVec 1023)) :
some 0#1023 =
if (BitVec.ofInt 1023 (-70368744177664) &&& 70368040490200#1023 != 0)
then none else none := by
/-
tactic 'simp' failed, nested error:
maximum recursion depth has been reached
use `set_option maxRecDepth <num>` to increase limit
use `set_option diagnostics true` to get diagnostic information
-/
/- equal to `simp only [reduceOfInt]`-/
simp? [-Int.reduceNeg, reduceOfInt, -reduceAnd, -ofNat_eq_ofNat,
-bne_self_eq_false, -Bool.false_eq_true, -reduceIte, -reduceCtorEq, -eq_self,
-bne_iff_ne, -ite_self, -Option.some_eq_ite_none_right, -Option.some_eq_ite_none_left
]
Which should be equal to simp only [reduceOfInt]
, but should not add eq_self to the simp set AFAIU.
Tobias Grosser (Dec 27 2024 at 22:14):
(deleted)
Henrik Böving (Dec 27 2024 at 22:17):
Yeah the simp.rewrit trace doesn't show it anymore like that but the defeq query remains, not clear to me what part of the system creates the defeq query then
Tobias Grosser (Dec 27 2024 at 22:18):
Is it possible that ground terms in an if-condition are somehow evaluated? Even though before reduction, the argument of the condition contained some variables.
Tobias Grosser (Dec 28 2024 at 07:12):
If I am not mistaken, simprocArrayCore
and simprocCore
seem to create these equalities at https://github.com/leanprover/lean4/blob/fe45ddd6105078a0a3bd855e5d94673e794f6b88/src/Lean/Meta/Tactic/Simp/Simproc.lean#L312 to apply the result of the simpproc.
Tobias Grosser (Dec 28 2024 at 07:26):
This also seems relevant:
/-- Given `h₁ : a = b` and `h₂ : b = c` returns a proof of `a = c`. -/
def mkEqTrans (h₁ h₂ : Expr) : MetaM Expr := do
if h₁.isAppOf ``Eq.refl then
return h₂
else if h₂.isAppOf ``Eq.refl then
return h₁
else
let hType₁ ← infer h₁
let hType₂ ← infer h₂
match hType₁.eq?, hType₂.eq? with
| some (α, a, b), some (_, _, c) =>
let u ← getLevel α
return mkApp6 (mkConst ``Eq.trans [u]) α a b c h₁ h₂
| none, _ => throwAppBuilderException ``Eq.trans ("equality proof expected" ++ hasTypeMsg h₁ hType₁)
| _, none => throwAppBuilderException ``Eq.trans ("equality proof expected" ++ hasTypeMsg h₂ hType₂)
Tobias Grosser (Dec 28 2024 at 07:26):
I guess mkEqTrans is creating Eq.refl
in our case?
Last updated: May 02 2025 at 03:31 UTC