Skip to content

Commit bd091f1

Browse files
authored
chore: fix bv_omega regression since v4.9.0 (#4579)
This example, reported from LNSym, started failing when we changed the definition of `Fin.sub` in #4421. When we use the new definition, `omega` produces a proof term that the kernel is very slow on. To work around this for now, I've removed `BitVec.toNat_sub` from the `bv_toNat` simp set, and replaced it with `BitVec.toNat_sub'` which uses the old definition for subtraction. This is only a workaround, and I would like to understand why the term chokes the kernel. ``` example (n : Nat) (addr2 addr1 : BitVec 64) (h0 : n ≤ 18446744073709551616) (h1 : addr2 + 18446744073709551615#64 - addr1 ≤ BitVec.ofNat 64 (n - 1)) (h2 : addr2 - addr1 ≤ addr2 + 18446744073709551615#64 - addr1) : n = 18446744073709551616 := by bv_omega ```
1 parent d8e719f commit bd091f1

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

src/Init/Data/BitVec/Lemmas.lean

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,16 @@ theorem ofInt_add {n} (x y : Int) : BitVec.ofInt n (x + y) =
10431043

10441044
theorem sub_def {n} (x y : BitVec n) : x - y = .ofNat n ((2^n - y.toNat) + x.toNat) := by rfl
10451045

1046-
@[simp, bv_toNat] theorem toNat_sub {n} (x y : BitVec n) :
1047-
(x - y).toNat = (((2^n - y.toNat) + x.toNat) % 2^n) := rfl
1046+
@[simp] theorem toNat_sub {n} (x y : BitVec n) :
1047+
(x - y).toNat = (((2^n - y.toNat) + x.toNat) % 2^n) := rfl
1048+
1049+
-- We prefer this lemma to `toNat_sub` for the `bv_toNat` simp set.
1050+
-- For reasons we don't yet understand, unfolding via `toNat_sub` sometimes
1051+
-- results in `omega` generating proof terms that are very slow in the kernel.
1052+
@[bv_toNat] theorem toNat_sub' {n} (x y : BitVec n) :
1053+
(x - y).toNat = ((x.toNat + (2^n - y.toNat)) % 2^n) := by
1054+
rw [toNat_sub, Nat.add_comm]
1055+
10481056
@[simp] theorem toFin_sub (x y : BitVec n) : (x - y).toFin = toFin x - toFin y := rfl
10491057

10501058
@[simp] theorem ofFin_sub (x : Fin (2^n)) (y : BitVec n) : .ofFin x - y = .ofFin (x - y.toFin) :=

tests/lean/run/omega.lean

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,31 @@ example (x y : BitVec 64) (_ : x < (y.truncate 32).zeroExtend 64) :
466466
~~~x > (1#64 <<< 63) := by
467467
bv_omega
468468

469+
-- This example, reported from LNSym,
470+
-- started failing when we changed the definition of `Fin.sub` in https://github.com/leanprover/lean4/pull/4421.
471+
-- When we use the new definition, `omega` produces a proof term that the kernel is very slow on.
472+
-- To work around this for now, I've removed `BitVec.toNat_sub` from the `bv_toNat` simp set,
473+
-- and replaced it with `BitVec.toNat_sub'` which uses the old definition for subtraction.
474+
-- This is only a workaround, and I would like to understand why the term chokes the kernel.
475+
example
476+
(n : Nat)
477+
(addr2 addr1 : BitVec 64)
478+
(h0 : n ≤ 18446744073709551616)
479+
(h1 : addr2 + 18446744073709551615#64 - addr1 ≤ BitVec.ofNat 64 (n - 1))
480+
(h2 : addr2 - addr1 ≤ addr2 + 18446744073709551615#64 - addr1) :
481+
n = 18446744073709551616 := by
482+
bv_omega
483+
484+
-- This smaller example exhibits the same problem.
485+
example
486+
(n : Nat)
487+
(addr2 addr1 : BitVec 16)
488+
(h0 : n ≤ 65536)
489+
(h1 : addr2 + 65535#16 - addr1 ≤ BitVec.ofNat 16 (n - 1))
490+
(h2 : addr2 - addr1 ≤ addr2 + 65535#16 - addr1) :
491+
n = 65536 := by
492+
bv_omega
493+
469494
/-! ### Error messages -/
470495

471496
/--

0 commit comments

Comments
 (0)