Theorem: Std.HashMap.Imp.expand_WF
File: Std/Data/HashMap/WF.lean

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

tactic: unfold expand.go
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
⊢ Bucket.WF (expand.go i source target)

tactic: split
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
⊢ Bucket.WF
    (if h : i < Array.size source then
      let idx := { val := i, isLt := h };
      let es := Array.get source idx;
      let source := Array.set source idx AssocList.nil;
      let target := AssocList.foldl reinsertAux target es;
      expand.go (i + 1) source target
    else target)

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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
⊢ Bucket.WF
    (let idx := { val := i, isLt := H };
    let es := Array.get source idx;
    let source := Array.set source idx AssocList.nil;
    let target := AssocList.foldl reinsertAux target es;
    expand.go (i + 1) source target)

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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
x✝ : AssocList α β
hl : x✝ ∈ (Array.set source { val := i, isLt := H } AssocList.nil).data
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList x✝)

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

tactic: exact e ▸ .nil
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝³ : BEq α
inst✝² : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
inst✝¹ : LawfulHashable α
inst✝ : PartialEquivBEq α
x✝ : AssocList α β
hl : x✝ ∈ (Array.set source { val := i, isLt := H } AssocList.nil).data
e : x✝ = AssocList.nil
⊢ List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList x✝)

tactic: simp [Array.getElem_eq_data_get, List.get_set]
state_before: case refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i✝) bucket
H : i✝ < Array.size source
i : Nat
h : i < Array.size (Array.set source { val := i✝, isLt := H } AssocList.nil)
⊢ AssocList.All
    (fun k x =>
      USize.toNat (UInt64.toUSize (hash k) % Array.size (Array.set source { val := i✝, isLt := H } AssocList.nil)) = i)
    (Array.set source { val := i✝, isLt := H } AssocList.nil)[i]

tactic: split
state_before: case refine_2
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i✝) bucket
H : i✝ < Array.size source
i : Nat
h : i < Array.size (Array.set source { val := i✝, isLt := H } AssocList.nil)
⊢ AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = i)
    (if i✝ = i then AssocList.nil else List.get source.data { val := i, isLt := (_ : i < List.length source.data) })

tactic: intro.
state_before: case refine_2.inl
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i✝) bucket
H : i✝ < Array.size source
i : Nat
h : i < Array.size (Array.set source { val := i✝, isLt := H } AssocList.nil)
h✝ : i✝ = i
⊢ AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = i) AssocList.nil

tactic: exact hs₂ _ (by simp_all)
state_before: case refine_2.inr
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i✝) bucket
H : i✝ < Array.size source
i : Nat
h : i < Array.size (Array.set source { val := i✝, isLt := H } AssocList.nil)
h✝ : ¬i✝ = i
⊢ AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = i)
    (List.get source.data { val := i, isLt := (_ : i < List.length source.data) })

tactic: simp_all
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i✝) bucket
H : i✝ < Array.size source
i : Nat
h : i < Array.size (Array.set source { val := i✝, isLt := H } AssocList.nil)
h✝ : ¬i✝ = i
⊢ i < Array.size source

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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
⊢ Bucket.WF (AssocList.foldl reinsertAux target (Array.get source { val := i, isLt := H })) ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (Array.get source { val := i, isLt := H })).val.data →
        AssocList.All
          (fun k x =>
            USize.toNat
                (UInt64.toUSize (hash k) % Array.size (Array.set source { val := i, isLt := H } AssocList.nil)) <
              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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
⊢ Bucket.WF (AssocList.foldl reinsertAux target (Array.get source { val := i, isLt := H })) ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (Array.get source { val := i, isLt := H })).val.data →
        AssocList.All
          (fun k x =>
            USize.toNat
                (UInt64.toUSize (hash k) % Array.size (Array.set source { val := i, isLt := H } AssocList.nil)) <
              i + 1)
          bucket

tactic: simp
state_before: case refine_3.refine_3
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
this :
  Bucket.WF (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])) ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data →
        AssocList.All (fun k x => rank k ≤ i) bucket
⊢ Bucket.WF (AssocList.foldl reinsertAux target (Array.get source { val := i, isLt := H })) ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (AssocList.foldl reinsertAux target (Array.get source { val := i, isLt := H })).val.data →
        AssocList.All
          (fun k x =>
            USize.toNat
                (UInt64.toUSize (hash k) % Array.size (Array.set source { val := i, isLt := H } AssocList.nil)) <
              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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
this :
  Bucket.WF (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])) ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data →
        AssocList.All (fun k x => rank k ≤ i) bucket
⊢ Bucket.WF (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])) ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i + 1) bucket

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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
⊢ ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α],
    List.Pairwise (fun a b => ¬(a.fst == b.fst) = true) (AssocList.toList source[i])

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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
x✝¹ : AssocList α β
h₁ : x✝¹ ∈ target.val.data
x✝ : α × β
h₂ : x✝ ∈ AssocList.toList x✝¹
⊢ (fun k x =>
      rank k ≤ i ∧
        ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α] (x : α × β),
          x ∈ AssocList.toList source[i] → ¬(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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
x✝¹ : AssocList α β
h₁ : x✝¹ ∈ target.val.data
x✝ : α × β
h₂ : x✝ ∈ AssocList.toList x✝¹
this : (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) x✝.fst x✝.snd
⊢ (fun k x =>
      rank k ≤ i ∧
        ∀ [inst : PartialEquivBEq α] [inst : LawfulHashable α] (x : α × β),
          x ∈ AssocList.toList source[i] → ¬(x.fst == k) = true)
    x✝.fst x✝.snd

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 : Bucket α β
H✝ : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
H : i < Array.size source
rank : α → Nat := fun k => USize.toNat (UInt64.toUSize (hash k) % Array.size source)
x✝² : AssocList α β
h₁ : x✝² ∈ target.val.data
x✝¹ : α × β
h₂ : x✝¹ ∈ AssocList.toList x✝²
this : (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) x✝¹.fst x✝¹.snd
inst✝¹ : PartialEquivBEq α
inst✝ : LawfulHashable α
x✝ : α × β
h : x✝ ∈ AssocList.toList source[i]
h' : (x✝.fst == x✝¹.fst) = true
⊢ USize.toNat (UInt64.toUSize (hash x✝¹.fst) % Array.size source) = i

tactic: exact ht.1
state_before: case inr
α : Type u_1
β : Type u_2
sz : Nat
inst✝¹ : BEq α
inst✝ : Hashable α
buckets : Bucket α β
H : Bucket.WF buckets
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) (AssocList.toList bucket)
hs₂ :
  ∀ (j : Nat) (h : j < Array.size source),
    AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) = j) source[j]
target : Bucket α β
ht :
  Bucket.WF target ∧
    ∀ (bucket : AssocList α β),
      bucket ∈ target.val.data →
        AssocList.All (fun k x => USize.toNat (UInt64.toUSize (hash k) % Array.size source) < i) bucket
h✝ : ¬i < Array.size source
⊢ Bucket.WF target