feat: add mem_of_get_eq and of_getElem_eq (#11452)

This PR adds lemmas stating that if a get operation returns a value,
then the queried key must be contained in the collection. These lemmas
are added for HashMap and TreeMap-based collections, with a similar
lemma also added for `Init.getElem`.
This commit is contained in:
Wojciech Różowski 2025-12-02 15:00:00 +00:00 committed by GitHub
parent a0c503cf2b
commit 8b7cbe7d2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 27 additions and 0 deletions

View file

@ -240,6 +240,9 @@ theorem getElem_of_getElem? [GetElem? cont idx elem dom] [LawfulGetElem cont idx
{c : cont} {i : idx} [Decidable (dom c i)] (h : c[i]? = some e) : Exists fun h : dom c i => c[i] = e :=
getElem?_eq_some_iff.mp h
theorem of_getElem_eq [GetElem? cont idx elem dom] [LawfulGetElem cont idx elem dom]
{c : cont} {i : idx} [Decidable (dom c i)] {h} (_ : c[i] = e) : dom c i := h
@[simp] theorem some_getElem_eq_getElem?_iff [GetElem? cont idx elem dom] [LawfulGetElem cont idx elem dom]
{c : cont} {i : idx} [Decidable (dom c i)] (h : dom c i):
(some c[i] = c[i]?) ↔ True := by

View file

@ -1115,6 +1115,8 @@ theorem getThenInsertIfNew?_snd [LawfulBEq α] {k : α} {v : β k} :
(m.getThenInsertIfNew? k v).2 = m.insertIfNew k v :=
ext <| congrArg Subtype.val (Raw₀.getThenInsertIfNew?_snd _ (k := k))
theorem mem_of_get_eq [LawfulBEq α] {k : α} {v : β k} {w} (_ : m.get k w = v) : k ∈ m := w
namespace Const
variable {β : Type v} {m : DHashMap α (fun _ => β)}

View file

@ -1181,6 +1181,8 @@ theorem getThenInsertIfNew?_snd [LawfulBEq α] (h : m.WF) {k : α} {v : β k} :
(m.getThenInsertIfNew? k v).2 = m.insertIfNew k v := by
simp_to_raw using congrArg Subtype.val (Raw₀.getThenInsertIfNew?_snd _)
theorem mem_of_get_eq [LawfulBEq α] {k : α} {v : β k} {w} (_ : m.get k w = v) : k ∈ m := w
namespace Const
variable {β : Type v} {m : DHashMap.Raw α (fun _ => β)} (h : m.WF)

View file

@ -1058,6 +1058,8 @@ theorem getThenInsertIfNew?_snd [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {v :
(t.getThenInsertIfNew? k v).2 = t.insertIfNew k v :=
ext <| Impl.getThenInsertIfNew?_snd t.wf
theorem mem_of_get_eq [LawfulEqCmp cmp] {k : α} {v : β k} {w} (_ : t.get k w = v) : k ∈ t := w
namespace Const
variable {β : Type v} {t : DTreeMap α β cmp}

View file

@ -1068,6 +1068,8 @@ theorem getThenInsertIfNew?_snd [TransCmp cmp] [LawfulEqCmp cmp] (h : t.WF) {k :
(t.getThenInsertIfNew? k v).2 = t.insertIfNew k v :=
ext <| Impl.getThenInsertIfNew?!_snd h
theorem mem_of_get_eq [LawfulEqCmp cmp] {k : α} {v : β k} {w} (_ : t.get k w = v) : k ∈ t := w
namespace Const
variable {β : Type v} {t : Raw α β cmp}

View file

@ -951,6 +951,8 @@ theorem getThenInsertIfNew?_snd [LawfulBEq α] {k : α} {v : β k} :
(m.getThenInsertIfNew? k v).2 = m.insertIfNew k v :=
m.inductionOn fun _ => congrArg mk DHashMap.getThenInsertIfNew?_snd
theorem mem_of_get_eq [LawfulBEq α] {k : α} {v : β k} {w} (_ : m.get k w = v) : k ∈ m := w
namespace Const
variable {β : Type v} {m : ExtDHashMap α (fun _ => β)}

View file

@ -1004,6 +1004,8 @@ theorem getThenInsertIfNew?_snd [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {v :
(t.getThenInsertIfNew? k v).2 = t.insertIfNew k v :=
t.inductionOn fun _ => congrArg mk DTreeMap.getThenInsertIfNew?_snd
theorem mem_of_get_eq [TransCmp cmp] [LawfulEqCmp cmp] {k : α} {v : β k} {w} (_ : t.get k w = v) : k ∈ t := w
namespace Const
variable {β : Type v} {t : ExtDTreeMap α β cmp}

View file

@ -123,6 +123,8 @@ theorem mem_of_mem_insert' [EquivBEq α] [LawfulHashable α] {k a : α} :
theorem contains_insert_self [EquivBEq α] [LawfulHashable α] {k : α} : (m.insert k).contains k := by
simp
theorem mem_of_get_eq [LawfulBEq α] (m : ExtHashSet α) {k v : α} {w} (_ : m.get k w = v) : k ∈ m := w
theorem mem_insert_self [EquivBEq α] [LawfulHashable α] {k : α} : k ∈ m.insert k := by simp
@[simp, grind =]

View file

@ -107,6 +107,8 @@ theorem contains_insert_self [TransCmp cmp] {k : α} :
(t.insert k).contains k :=
ExtTreeMap.contains_insertIfNew_self
theorem mem_of_get_eq [TransCmp cmp] {k v : α} {w} (_ : t.get k w = v) : k ∈ t := w
theorem mem_insert_self [TransCmp cmp] {k : α} :
k ∈ t.insert k :=
ExtTreeMap.mem_insertIfNew_self

View file

@ -140,6 +140,8 @@ theorem contains_insert_self [EquivBEq α] [LawfulHashable α] {k : α} : (m.ins
theorem mem_insert_self [EquivBEq α] [LawfulHashable α] {k : α} : k ∈ m.insert k := by simp
theorem mem_of_get_eq {k v : α} {w} (_ : m.get k w = v) : k ∈ m := w
@[simp, grind =]
theorem size_emptyWithCapacity {c} : (emptyWithCapacity c : HashSet α).size = 0 :=
HashMap.size_emptyWithCapacity

View file

@ -167,6 +167,8 @@ theorem contains_insert_self [EquivBEq α] [LawfulHashable α] (h : m.WF) {k :
theorem mem_insert_self [EquivBEq α] [LawfulHashable α] (h : m.WF) {k : α} : k ∈ m.insert k :=
HashMap.Raw.mem_insertIfNew_self h.out
theorem mem_of_get_eq {k v : α} {w} (_ : m.get k w = v) : k ∈ m := w
@[grind =] theorem size_insert [EquivBEq α] [LawfulHashable α] (h : m.WF) {k : α} :
(m.insert k).size = if k ∈ m then m.size else m.size + 1 :=
HashMap.Raw.size_insertIfNew h.out

View file

@ -114,6 +114,8 @@ theorem contains_insert_self [TransCmp cmp] {k : α} :
(t.insert k).contains k :=
TreeMap.contains_insertIfNew_self
theorem mem_of_get_eq {k v : α} {w} (_ : t.get k w = v) : k ∈ t := w
theorem mem_insert_self [TransCmp cmp] {k : α} :
k ∈ t.insert k :=
TreeMap.mem_insertIfNew_self

View file

@ -116,6 +116,8 @@ theorem contains_insert_self [TransCmp cmp] (h : t.WF) {k : α} :
(t.insert k).contains k :=
TreeMap.Raw.contains_insertIfNew_self h
theorem mem_of_get_eq {k v : α} {w} (_ : t.get k w = v) : k ∈ t := w
theorem mem_insert_self [TransCmp cmp] (h : t.WF) {k : α} :
k ∈ t.insert k :=
TreeMap.Raw.mem_insertIfNew_self h