Zulip Chat Archive
Stream: new members
Topic: dependent elimination failed when running `case heq`
One Happy Fellow (Dec 10 2025 at 14:08):
Hi all,
I'm doing proofs on BitVecs and I want to state a correctness property equating two BitVecs which don't have definitionally equal type parameters, only equal ones.
On line 45 of the linked code, lean complains that "dependent elimination failed" - I'm completely lost here, what does that error mean? What's the best way to resolve it?
Thanks all!
#mwe:
open BitVec
structure ShaBlock where
block : Array (BitVec 32)
hlen : block.size = 16 := by grind
def ShaBlock.ofBits (b : BitVec 512) : ShaBlock :=
let block : Array (BitVec 32) :=
Array.range (512/32) |>.map fun i =>
have heq : (((i+1)*32-1) - i*32 + 1) = 32 := by omega
heq ▸ (b.extractLsb ((i+1)*32-1) (i*32))
have hlen : block.size = 16 := by
unfold block
rw [Array.size_map, Array.size_range]
{ block, hlen := hlen }
def concatBitVecArray'
{n : Nat}
(a : Array (BitVec n))
(i : Nat)
(hlen : i ≤ a.size)
(acc : BitVec (i * n)) : BitVec (a.size * n) :=
if heq : i = a.size
then by rw [←heq]; exact acc
else
have hlen : i < a.size := by omega
have heq : (i + 1) * n = i * n + n := by
rw [Nat.mul_comm, Nat.mul_add]; simp; rw [Nat.mul_comm]
let acc : BitVec ((i + 1) * n) := by
rw [heq]
exact acc ++ a[i]
have hlen : i + 1 ≤ a.size := by omega
concatBitVecArray' a (i+1) hlen acc
def concatBitVecArray {n : Nat} (a : Array (BitVec n)) : BitVec (a.size * n) :=
concatBitVecArray' a 0 (by simp) (by simp; exact BitVec.ofNat 0 0)
set_option diagnostics true
theorem ShaBlocks.ofBits_sound (b : BitVec 512) :
have hlen : (ShaBlock.ofBits b).block.size * 32 = 512 := by
rw [(ShaBlock.ofBits b).hlen]
hlen ▸ concatBitVecArray (ShaBlock.ofBits b).block = b := by
intro hlen
cases hlen
sorry
Etienne Marion (Dec 10 2025 at 14:09):
It's better to use #backticks to send code, it automatically puts a button to open the code in the web editor.
One Happy Fellow (Dec 10 2025 at 14:09):
Thank you, I edited the message!
Kyle Miller (Dec 10 2025 at 17:25):
With (ShaBlock.ofBits b).block.size * 32 = 512, the only way cases could succeed is if it can turn this into some equations where one side is a variable. In this case, neither side is obviously a variable.
Kyle Miller (Dec 10 2025 at 17:31):
Hint about working with parameterized types: using rewrite tactics and the triangle operator in definitions can lead to a lot of pain. You can use functions like docs#BitVec.cast to have finer-grained control of the rewrite, and there are simp lemmas about such functions.
open BitVec
structure ShaBlock where
block : Array (BitVec 32)
hlen : block.size = 16 := by grind
def ShaBlock.ofBits (b : BitVec 512) : ShaBlock :=
let block : Array (BitVec 32) :=
Array.range (512/32) |>.map fun i =>
(b.extractLsb ((i+1)*32-1) (i*32)).cast (by omega)
have hlen : block.size = 16 := by
unfold block
rw [Array.size_map, Array.size_range]
{ block, hlen := hlen }
def concatBitVecArray'
{n : Nat}
(a : Array (BitVec n))
(i : Nat)
(hlen : i ≤ a.size)
(acc : BitVec (i * n)) : BitVec (a.size * n) :=
if heq : i = a.size
then acc.cast (by rw [heq])
else
have hlen : i < a.size := by omega
have heq : (i + 1) * n = i * n + n := by
rw [Nat.mul_comm, Nat.mul_add]; simp; rw [Nat.mul_comm]
let acc : BitVec ((i + 1) * n) :=
(acc ++ a[i]).cast heq.symm
have hlen : i + 1 ≤ a.size := by omega
concatBitVecArray' a (i+1) hlen acc
def concatBitVecArray {n : Nat} (a : Array (BitVec n)) : BitVec (a.size * n) :=
concatBitVecArray' a 0 (by simp) ((BitVec.ofNat 0 0).cast (by simp))
set_option diagnostics true
theorem ShaBlocks.ofBits_sound (b : BitVec 512) :
haveI hlen : (ShaBlock.ofBits b).block.size * 32 = 512 := by
rw [(ShaBlock.ofBits b).hlen]
(concatBitVecArray (ShaBlock.ofBits b).block).cast hlen = b := by
sorry
Kyle Miller (Dec 10 2025 at 17:37):
That doesn't get you much closer to proving the goal — it will be some induction argument — but hopefully it helps avoid rewriting-data-induced problems.
One Happy Fellow (Dec 10 2025 at 19:27):
Thank you, I can handle proving the goal but I was stuck at getting rid of the triangle operator.
One Happy Fellow (Dec 10 2025 at 19:28):
using rewrite tactics and the triangle operator in definitions can lead to a lot of pain
How would I avoid using rewrite lemmas and triangle operator here?
Kyle Miller (Dec 10 2025 at 21:18):
The code I gave eliminated it.
Last updated: Dec 20 2025 at 21:32 UTC