Theorem: Batteries.HashMap.Imp.expand_WF
File: .lake/packages/batteries/Batteries/Data/HashMap/WF.lean

tactic: simp_all [Buckets.mk, List.mem_replicate]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
x✝³ : AssocList α β
x✝² : x✝³ ∈ (Buckets.mk (buckets.val.size * 2) ⋯).val.data
x✝¹ : α × β
x✝ : x✝¹ ∈ x✝³.toList
⊢ (fun k x => ((hash k).toUSize % buckets.val.size).toNat < 0) x✝¹.fst x✝¹.snd
state_after: no goals

tactic: unfold expand.go
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
⊢ (expand.go i source target).WF
state_after: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
⊢ (if h : i < source.size then
      let idx := ⟨i, h⟩;
      let es := source.get idx;
      let source := source.set idx AssocList.nil;
      let target := AssocList.foldl reinsertAux target es;
      expand.go (i + 1) source target
    else target).WF

tactic: split
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
⊢ (if h : i < source.size then
      let idx := ⟨i, h⟩;
      let es := source.get idx;
      let source := source.set idx AssocList.nil;
      let target := AssocList.foldl reinsertAux target es;
      expand.go (i + 1) source target
    else target).WF
state_after: case isTrue
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
h✝ : i < source.size
⊢ (let idx := ⟨i, h✝⟩;
    let es := source.get idx;
    let source := source.set idx AssocList.nil;
    let target := AssocList.foldl reinsertAux target es;
    expand.go (i + 1) source target).WF

case isFalse
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
h✝ : ¬i < source.size
⊢ target.WF

tactic: refine go (i+1) (fun _ hl => ?_) (fun i h => ?_) ?_
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
⊢ (let idx := ⟨i, H⟩;
    let es := source.get idx;
    let source := source.set idx AssocList.nil;
    let target := AssocList.foldl reinsertAux target es;
    expand.go (i + 1) source target).WF
state_after: case refine_1
α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
x✝ : AssocList α β
hl : x✝ ∈ (source.set ⟨i, H⟩ AssocList.nil).data
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) x✝.toList

case refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
⊢ AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i✝, H⟩ AssocList.nil).size).toNat = i)
    (source.set ⟨i✝, H⟩ AssocList.nil)[i]

case refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
⊢ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i, H⟩ AssocList.nil).size).toNat < i + 1) bucket

tactic: match List.mem_or_eq_of_mem_set hl with
| .inl hl => exact hs₁ _ hl
| .inr e => exact e ▸ .nil
state_before: case refine_1
α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
x✝ : AssocList α β
hl : x✝ ∈ (source.set ⟨i, H⟩ AssocList.nil).data
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) x✝.toList
state_after: no goals

tactic: exact hs₁ _ hl
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
x✝ : AssocList α β
hl✝ : x✝ ∈ (source.set ⟨i, H⟩ AssocList.nil).data
hl : x✝ ∈ source.data
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) x✝.toList
state_after: no goals

tactic: exact e ▸ .nil
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
x✝ : AssocList α β
hl : x✝ ∈ (source.set ⟨i, H⟩ AssocList.nil).data
e : x✝ = AssocList.nil
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) x✝.toList
state_after: no goals

tactic: simp only [Array.data_length, Array.size_set, Array.getElem_eq_data_getElem, Array.data_set,
  List.getElem_set]
state_before: case refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
⊢ AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i✝, H⟩ AssocList.nil).size).toNat = i)
    (source.set ⟨i✝, H⟩ AssocList.nil)[i]
state_after: case refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
⊢ AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = i)
    (if i✝ = i then AssocList.nil else source.data[i])

tactic: split
state_before: case refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
⊢ AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = i)
    (if i✝ = i then AssocList.nil else source.data[i])
state_after: case refine_2.isTrue
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
h✝ : i✝ = i
⊢ AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = i) AssocList.nil

case refine_2.isFalse
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
h✝ : ¬i✝ = i
⊢ AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = i) source.data[i]

tactic: nofun
state_before: case refine_2.isTrue
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
h✝ : i✝ = i
⊢ AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = i) AssocList.nil
state_after: no goals

tactic: exact hs₂ _ (by simp_all)
state_before: case refine_2.isFalse
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
h✝ : ¬i✝ = i
⊢ AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = i) source.data[i]
state_after: no goals

tactic: simp_all
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i✝ : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i✝) bucket
H : i✝ < source.size
i : Nat
h : i < (source.set ⟨i✝, H⟩ AssocList.nil).size
h✝ : ¬i✝ = i
⊢ i < source.size
state_after: no goals

tactic: let rank (k : α) := ((hash k).toUSize % source.size).toNat
state_before: case refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
⊢ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i, H⟩ AssocList.nil).size).toNat < i + 1) bucket
state_after: case refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
⊢ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i, H⟩ AssocList.nil).size).toNat < i + 1) bucket

tactic: have := expand_WF.foldl rank ?_ (hs₂ _ H) ht.1 (fun _ h₁ _ h₂ => ?_)
state_before: case refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
⊢ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i, H⟩ AssocList.nil).size).toNat < i + 1) bucket
state_after: case refine_3.refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
this :
  (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).val.data →
        AssocList.All (fun k x => rank k ≤ i) bucket
⊢ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i, H⟩ AssocList.nil).size).toNat < i + 1) bucket

case refine_3.refine_1
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
⊢ ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) source[i].toList

case refine_3.refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
x✝¹ : AssocList α β
h₁ : x✝¹ ∈ target.val.data
x✝ : α × β
h₂ : x✝ ∈ x✝¹.toList
⊢ (fun k x =>
      rank k ≤ i ∧
        ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α] (x : α × β), x ∈ source[i].toList → ¬(x.fst == k) = true)
    x✝.fst x✝.snd

tactic: simp only [Array.get_eq_getElem, AssocList.foldl_eq, Array.size_set]
state_before: case refine_3.refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
this :
  (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).val.data →
        AssocList.All (fun k x => rank k ≤ i) bucket
⊢ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (source.get ⟨i, H⟩)).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % (source.set ⟨i, H⟩ AssocList.nil).size).toNat < i + 1) bucket
state_after: case refine_3.refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
this :
  (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).val.data →
        AssocList.All (fun k x => rank k ≤ i) bucket
⊢ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i + 1) bucket

tactic: exact ⟨this.1, fun _ h₁ _ h₂ => Nat.lt_succ_of_le (this.2 _ h₁ _ h₂)⟩
state_before: case refine_3.refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
this :
  (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).val.data →
        AssocList.All (fun k x => rank k ≤ i) bucket
⊢ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target source[i].toList).val.data →
        AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i + 1) bucket
state_after: no goals

tactic: exact hs₁ _ (Array.getElem_mem_data ..)
state_before: case refine_3.refine_1
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
⊢ ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) source[i].toList
state_after: no goals

tactic: have := ht.2 _ h₁ _ h₂
state_before: case refine_3.refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
x✝¹ : AssocList α β
h₁ : x✝¹ ∈ target.val.data
x✝ : α × β
h₂ : x✝ ∈ x✝¹.toList
⊢ (fun k x =>
      rank k ≤ i ∧
        ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α] (x : α × β), x ∈ source[i].toList → ¬(x.fst == k) = true)
    x✝.fst x✝.snd
state_after: case refine_3.refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
x✝¹ : AssocList α β
h₁ : x✝¹ ∈ target.val.data
x✝ : α × β
h₂ : x✝ ∈ x✝¹.toList
this : (fun k x => ((hash k).toUSize % source.size).toNat < i) x✝.fst x✝.snd
⊢ (fun k x =>
      rank k ≤ i ∧
        ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α] (x : α × β), x ∈ source[i].toList → ¬(x.fst == k) = true)
    x✝.fst x✝.snd

tactic: refine ⟨Nat.le_of_lt this, fun _ h h' => Nat.ne_of_lt this ?_⟩
state_before: case refine_3.refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
x✝¹ : AssocList α β
h₁ : x✝¹ ∈ target.val.data
x✝ : α × β
h₂ : x✝ ∈ x✝¹.toList
this : (fun k x => ((hash k).toUSize % source.size).toNat < i) x✝.fst x✝.snd
⊢ (fun k x =>
      rank k ≤ i ∧
        ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α] (x : α × β), x ∈ source[i].toList → ¬(x.fst == k) = true)
    x✝.fst x✝.snd
state_after: case refine_3.refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
x✝² : AssocList α β
h₁ : x✝² ∈ target.val.data
x✝¹ : α × β
h₂ : x✝¹ ∈ x✝².toList
this : (fun k x => ((hash k).toUSize % source.size).toNat < i) x✝¹.fst x✝¹.snd
inst✝¹ : PartialEquivBEq α
inst✝ : LawfulHashable α
x✝ : α × β
h : x✝ ∈ source[i].toList
h' : (x✝.fst == x✝¹.fst) = true
⊢ ((hash x✝¹.fst).toUSize % source.size).toNat = i

tactic: exact LawfulHashable.hash_eq h' ▸ hs₂ _ H _ h
state_before: case refine_3.refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Buckets α β
H✝ : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
H : i < source.size
rank : α → Nat := fun k => ((hash k).toUSize % source.size).toNat
x✝² : AssocList α β
h₁ : x✝² ∈ target.val.data
x✝¹ : α × β
h₂ : x✝¹ ∈ x✝².toList
this : (fun k x => ((hash k).toUSize % source.size).toNat < i) x✝¹.fst x✝¹.snd
inst✝¹ : PartialEquivBEq α
inst✝ : LawfulHashable α
x✝ : α × β
h : x✝ ∈ source[i].toList
h' : (x✝.fst == x✝¹.fst) = true
⊢ ((hash x✝¹.fst).toUSize % source.size).toNat = i
state_after: no goals

tactic: exact ht.1
state_before: case isFalse
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Buckets α β
H : buckets.WF
i : Nat
source : Array (AssocList α β)
hs₁ :
  ∀ [inst : LawfulHashable α] [inst : PartialEquivBEq α] (bucket : AssocList α β),
    bucket ∈ source.data → List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) bucket.toList
hs₂ : ∀ (j : Nat) (h : j < source.size), AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat = j) source[j]
target : Buckets α β
ht :
  target.WF ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data → AssocList.All (fun k x => ((hash k).toUSize % source.size).toNat < i) bucket
h✝ : ¬i < source.size
⊢ target.WF
state_after: no goals