Theorem: Std.HashMap.Imp.Bucket.WF.update
File: Std/Data/HashMap/WF.lean

tactic: refine ⟨fun l hl => ?_, fun i hi p hp => ?_⟩
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i : USize
d : AssocList α β
h : USize.toNat i < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i)
      buckets.val[i] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i) d
⊢ WF (Bucket.update buckets i d h)

tactic: exact match List.mem_or_eq_of_mem_set hl with
| .inl hl => H.1 _ hl
| .inr rfl => h₁ (H.1 _ (Array.getElem_mem_data ..))
state_before: case refine_1
α : Type u_1
β : Type u_2
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Bucket α β
i : USize
d : AssocList α β
h : USize.toNat i < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i)
      buckets.val[i] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i) d
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
l : AssocList α β
hl : l ∈ (Bucket.update buckets i d h).val.data
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList l)

tactic: revert hp
state_before: case refine_2
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
hp : p ∈ AssocList.toList (Bucket.update buckets i✝ d h).val[i]
⊢ (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size (Bucket.update buckets i✝ d h).val) = i) p.fst p.snd

tactic: simp [update_data, Array.getElem_eq_data_get, List.get_set]
state_before: case refine_2
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
⊢ p ∈ AssocList.toList (Bucket.update buckets i✝ d h).val[i] →
    (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size (Bucket.update buckets i✝ d h).val) = i) p.fst p.snd

tactic: split <;> intro hp
state_before: case refine_2
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
⊢ p ∈
      AssocList.toList
        (if USize.toNat i✝ = i then d
        else List.get buckets.val.data { val := i, isLt := (_ : i < List.length buckets.val.data) }) →
    USize.toNat (UInt64.toUSize (hash p.fst) % Array.size buckets.val) = i

tactic: next eq => exact eq ▸ h₂ (H.2 _ _) _ hp
state_before: case refine_2.inl
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
h✝ : USize.toNat i✝ = i
hp : p ∈ AssocList.toList d
⊢ USize.toNat (UInt64.toUSize (hash p.fst) % Array.size buckets.val) = i

tactic: exact eq ▸ h₂ (H.2 _ _) _ hp
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
eq : USize.toNat i✝ = i
hp : p ∈ AssocList.toList d
⊢ USize.toNat (UInt64.toUSize (hash p.fst) % Array.size buckets.val) = i

tactic: simp at hi
state_before: case refine_2.inr
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
h✝ : ¬USize.toNat i✝ = i
hp : p ∈ AssocList.toList (List.get buckets.val.data { val := i, isLt := (_ : i < List.length buckets.val.data) })
⊢ USize.toNat (UInt64.toUSize (hash p.fst) % Array.size buckets.val) = i

tactic: exact H.2 i hi _ hp
state_before: case refine_2.inr
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
i✝ : USize
d : AssocList α β
h : USize.toNat i✝ < Array.size buckets.val
H : WF buckets
h₁ :
  ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList buckets.val[i✝]) →
      List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList d)
h₂ :
  AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝)
      buckets.val[i✝] →
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size buckets.val) = USize.toNat i✝) d
i : Nat
hi✝ : i < Array.size (Bucket.update buckets i✝ d h).val
p : α × β
h✝ : ¬USize.toNat i✝ = i
hp : p ∈ AssocList.toList (List.get buckets.val.data { val := i, isLt := (_ : i < List.length buckets.val.data) })
hi : i < Array.size buckets.val
⊢ USize.toNat (UInt64.toUSize (hash p.fst) % Array.size buckets.val) = i