feat: add grind_pattern constraint annotations (#11193)
This PR uses the new `grind_pattern` constraints to fix cases where an unbounded number of theorem instantiations would be generated for certain theorems in the standard library.
This commit is contained in:
parent
e39894e62d
commit
f4cd97ce04
10 changed files with 62 additions and 55 deletions
|
|
@ -100,9 +100,15 @@ abbrev push_toList := @toList_push
|
|||
@[simp, grind =] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
|
||||
apply ext'; simp only [toList_append, List.nil_append]
|
||||
|
||||
@[simp, grind _=_] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
|
||||
@[simp] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
|
||||
apply ext'; simp only [toList_append, List.append_assoc]
|
||||
|
||||
grind_pattern append_assoc => (xs ++ ys) ++ zs where
|
||||
xs =/= #[]; ys =/= #[]; zs =/= #[]
|
||||
|
||||
grind_pattern append_assoc => xs ++ (ys ++ zs) where
|
||||
xs =/= #[]; ys =/= #[]; zs =/= #[]
|
||||
|
||||
@[simp] theorem appendList_eq_append {xs : Array α} {l : List α} : xs.appendList l = xs ++ l := rfl
|
||||
|
||||
@[simp, grind =] theorem toList_appendList {xs : Array α} {l : List α} :
|
||||
|
|
@ -110,6 +116,4 @@ abbrev push_toList := @toList_push
|
|||
rw [← appendList_eq_append]; unfold Array.appendList
|
||||
induction l generalizing xs <;> simp [*]
|
||||
|
||||
|
||||
|
||||
end Array
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ theorem getElem?_extract_of_succ {as : Array α} {j : Nat} :
|
|||
simp [getElem?_extract]
|
||||
omega
|
||||
|
||||
@[simp, grind =] theorem extract_extract {as : Array α} {i j k l : Nat} :
|
||||
@[simp] theorem extract_extract {as : Array α} {i j k l : Nat} :
|
||||
(as.extract i j).extract k l = as.extract (i + k) (min (i + l) j) := by
|
||||
ext m h₁ h₂
|
||||
· simp
|
||||
|
|
@ -208,6 +208,9 @@ theorem getElem?_extract_of_succ {as : Array α} {j : Nat} :
|
|||
· simp only [size_extract] at h₁ h₂
|
||||
simp [Nat.add_assoc]
|
||||
|
||||
grind_pattern extract_extract => (as.extract i j).extract k l where
|
||||
as =/= #[]
|
||||
|
||||
theorem extract_eq_empty_of_eq_empty {as : Array α} {i j : Nat} (h : as = #[]) :
|
||||
as.extract i j = #[] := by
|
||||
simp [h]
|
||||
|
|
|
|||
|
|
@ -1628,12 +1628,15 @@ theorem filterMap_eq_filter {p : α → Bool} (w : stop = as.size) :
|
|||
cases as
|
||||
simp
|
||||
|
||||
@[grind =]
|
||||
theorem filterMap_filterMap {f : α → Option β} {g : β → Option γ} {xs : Array α} :
|
||||
filterMap g (filterMap f xs) = filterMap (fun x => (f x).bind g) xs := by
|
||||
cases xs
|
||||
simp [List.filterMap_filterMap]
|
||||
|
||||
grind_pattern filterMap_filterMap => filterMap g (filterMap f xs) where
|
||||
f =/= some
|
||||
g =/= some
|
||||
|
||||
@[grind =]
|
||||
theorem map_filterMap {f : α → Option β} {g : β → γ} {xs : Array α} :
|
||||
map g (filterMap f xs) = filterMap (fun x => (f x).map g) xs := by
|
||||
|
|
|
|||
|
|
@ -24,12 +24,17 @@ theorem natCast_shiftRight (n s : Nat) : n >>> s = (n : Int) >>> s := rfl
|
|||
theorem negSucc_shiftRight (m n : Nat) :
|
||||
-[m+1] >>> n = -[m >>>n +1] := rfl
|
||||
|
||||
@[grind _=_]
|
||||
theorem shiftRight_add (i : Int) (m n : Nat) :
|
||||
i >>> (m + n) = i >>> m >>> n := by
|
||||
simp only [shiftRight_eq, Int.shiftRight]
|
||||
cases i <;> simp [Nat.shiftRight_add]
|
||||
|
||||
grind_pattern shiftRight_add => i >>> (m + n) where
|
||||
i =/= 0
|
||||
|
||||
grind_pattern shiftRight_add => i >>> m >>> n where
|
||||
i =/= 0
|
||||
|
||||
theorem shiftRight_eq_div_pow (m : Int) (n : Nat) :
|
||||
m >>> n = m / ((2 ^ n) : Nat) := by
|
||||
simp only [shiftRight_eq, Int.shiftRight, Nat.shiftRight_eq_div_pow]
|
||||
|
|
|
|||
|
|
@ -622,11 +622,17 @@ instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where
|
|||
| nil => simp
|
||||
| cons _ as ih => simp [ih, Nat.succ_add]
|
||||
|
||||
@[simp, grind _=_] theorem append_assoc (as bs cs : List α) : (as ++ bs) ++ cs = as ++ (bs ++ cs) := by
|
||||
@[simp] theorem append_assoc (as bs cs : List α) : (as ++ bs) ++ cs = as ++ (bs ++ cs) := by
|
||||
induction as with
|
||||
| nil => rfl
|
||||
| cons a as ih => simp [ih]
|
||||
|
||||
grind_pattern append_assoc => (as ++ bs) ++ cs where
|
||||
as =/= []; bs =/= []; cs =/= []
|
||||
|
||||
grind_pattern append_assoc => as ++ (bs ++ cs) where
|
||||
as =/= []; bs =/= []; cs =/= []
|
||||
|
||||
instance : Std.Associative (α := List α) (· ++ ·) := ⟨append_assoc⟩
|
||||
|
||||
-- Arguments are explicit as there is often ambiguity inferring the arguments.
|
||||
|
|
|
|||
|
|
@ -1217,9 +1217,13 @@ theorem tailD_map {f : α → β} {l l' : List α} :
|
|||
theorem getLastD_map {f : α → β} {l : List α} {a : α} : (map f l).getLastD (f a) = f (l.getLastD a) := by
|
||||
simp
|
||||
|
||||
@[simp, grind _=_] theorem map_map {g : β → γ} {f : α → β} {l : List α} :
|
||||
@[simp] theorem map_map {g : β → γ} {f : α → β} {l : List α} :
|
||||
map g (map f l) = map (g ∘ f) l := by induction l <;> simp_all
|
||||
|
||||
grind_pattern map_map => map g (map f l) where
|
||||
g =/= List.reverse
|
||||
f =/= List.reverse
|
||||
|
||||
/-! ### filter -/
|
||||
|
||||
@[simp] theorem filter_cons_of_pos {p : α → Bool} {a : α} {l} (pa : p a) :
|
||||
|
|
@ -1428,13 +1432,16 @@ theorem filterMap_eq_filter {p : α → Bool} :
|
|||
| nil => rfl
|
||||
| cons a l IH => by_cases pa : p a <;> simp [Option.guard, pa, ← IH]
|
||||
|
||||
@[grind =]
|
||||
theorem filterMap_filterMap {f : α → Option β} {g : β → Option γ} {l : List α} :
|
||||
filterMap g (filterMap f l) = filterMap (fun x => (f x).bind g) l := by
|
||||
induction l with
|
||||
| nil => rfl
|
||||
| cons a l IH => cases h : f a <;> simp [filterMap_cons, *]
|
||||
|
||||
grind_pattern filterMap_filterMap => filterMap g (filterMap f l) where
|
||||
f =/= some
|
||||
g =/= some
|
||||
|
||||
@[grind =]
|
||||
theorem map_filterMap {f : α → Option β} {g : β → γ} {l : List α} :
|
||||
map g (filterMap f l) = filterMap (fun x => (f x).map g) l := by
|
||||
|
|
|
|||
|
|
@ -68,10 +68,13 @@ theorem getElem?_modifyHead {l : List α} {f : α → α} {i} :
|
|||
@[simp, grind =] theorem tail_modifyHead {f : α → α} {l : List α} :
|
||||
(l.modifyHead f).tail = l.tail := by cases l <;> simp
|
||||
|
||||
@[simp, grind =] theorem take_modifyHead {f : α → α} {l : List α} {i} :
|
||||
@[simp] theorem take_modifyHead {f : α → α} {l : List α} {i} :
|
||||
(l.modifyHead f).take i = (l.take i).modifyHead f := by
|
||||
cases l <;> cases i <;> simp
|
||||
|
||||
grind_pattern take_modifyHead => (l.modifyHead f).take i where
|
||||
i =/= 0
|
||||
|
||||
@[simp] theorem drop_modifyHead_of_pos {f : α → α} {l : List α} {i} (h : 0 < i) :
|
||||
(l.modifyHead f).drop i = l.drop i := by
|
||||
cases l <;> cases i <;> simp_all
|
||||
|
|
@ -213,7 +216,6 @@ theorem modify_eq_self {f : α → α} {i} {l : List α} (h : l.length ≤ i) :
|
|||
intro h
|
||||
omega
|
||||
|
||||
@[grind =]
|
||||
theorem modify_modify_eq (f g : α → α) (i) (l : List α) :
|
||||
(l.modify i f).modify i g = l.modify i (g ∘ f) := by
|
||||
apply ext_getElem
|
||||
|
|
@ -222,6 +224,9 @@ theorem modify_modify_eq (f g : α → α) (i) (l : List α) :
|
|||
simp only [getElem_modify, Function.comp_apply]
|
||||
split <;> simp
|
||||
|
||||
grind_pattern modify_modify_eq => (l.modify i f).modify i g where
|
||||
l =/= []
|
||||
|
||||
theorem modify_modify_ne (f g : α → α) {i j} (l : List α) (h : i ≠ j) :
|
||||
(l.modify i f).modify j g = (l.modify j g).modify i f := by
|
||||
apply ext_getElem
|
||||
|
|
|
|||
|
|
@ -485,11 +485,16 @@ protected theorem and_comm (x y : Nat) : x &&& y = y &&& x := by
|
|||
apply Nat.eq_of_testBit_eq
|
||||
simp [Bool.and_comm]
|
||||
|
||||
@[grind _=_]
|
||||
protected theorem and_assoc (x y z : Nat) : (x &&& y) &&& z = x &&& (y &&& z) := by
|
||||
apply Nat.eq_of_testBit_eq
|
||||
simp [Bool.and_assoc]
|
||||
|
||||
grind_pattern Nat.and_assoc => (x &&& y) &&& z where
|
||||
x =/= 0; y =/= 0; z =/= 0
|
||||
|
||||
grind_pattern Nat.and_assoc => x &&& (y &&& z) where
|
||||
x =/= 0; y =/= 0; z =/= 0
|
||||
|
||||
instance : Std.Associative (α := Nat) (· &&& ·) where
|
||||
assoc := Nat.and_assoc
|
||||
|
||||
|
|
|
|||
|
|
@ -1719,11 +1719,16 @@ theorem shiftRight_succ_inside : ∀m n, m >>> (n+1) = (m/2) >>> n
|
|||
| 0 => by simp
|
||||
| n + 1 => by simp [zero_shiftRight n, shiftRight_succ]
|
||||
|
||||
@[grind _=_]
|
||||
theorem shiftLeft_add (m n : Nat) : ∀ k, m <<< (n + k) = (m <<< n) <<< k
|
||||
| 0 => rfl
|
||||
| k + 1 => by simp [← Nat.add_assoc, shiftLeft_add _ _ k, shiftLeft_succ]
|
||||
|
||||
grind_pattern shiftLeft_add => m <<< (n + k) where
|
||||
m =/= 0
|
||||
|
||||
grind_pattern shiftLeft_add => (m <<< n) <<< k where
|
||||
m =/= 0
|
||||
|
||||
@[simp] theorem shiftLeft_shiftRight (x n : Nat) : x <<< n >>> n = x := by
|
||||
rw [Nat.shiftLeft_eq, Nat.shiftRight_eq_div_pow, Nat.mul_div_cancel _ (Nat.two_pow_pos _)]
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ error: `Array.swap_swap` is not marked with the `@[grind]` attribute for theorem
|
|||
#grind_lint skip Array.getElem_swap
|
||||
|
||||
/--
|
||||
info: instantiating `Array.range_succ` triggers 47 additional `grind` theorem instantiations
|
||||
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
||||
---
|
||||
info: Try this to display the actual theorem instances:
|
||||
[apply] set_option trace.grind.ematch.instance true in
|
||||
|
|
@ -37,7 +37,7 @@ info: Try this to display the actual theorem instances:
|
|||
#grind_lint mute Array.append_assoc -- It is not used during E-matching by `#grind_lint check` and `#grind_lint inspect`
|
||||
|
||||
/--
|
||||
info: instantiating `Array.range_succ` triggers 22 additional `grind` theorem instantiations
|
||||
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
||||
---
|
||||
info: Try this to display the actual theorem instances:
|
||||
[apply] set_option trace.grind.ematch.instance true in
|
||||
|
|
@ -47,9 +47,9 @@ info: Try this to display the actual theorem instances:
|
|||
#grind_lint inspect Array.range_succ
|
||||
|
||||
/--
|
||||
info: instantiating `Array.range_succ` triggers 22 additional `grind` theorem instantiations
|
||||
info: instantiating `Array.range_succ` triggers 19 additional `grind` theorem instantiations
|
||||
---
|
||||
info: instantiating `Array.range'_succ` triggers 17 additional `grind` theorem instantiations
|
||||
info: instantiating `Array.range'_succ` triggers 14 additional `grind` theorem instantiations
|
||||
---
|
||||
info: Try this to display the actual theorem instances:
|
||||
[apply] set_option trace.grind.ematch.instance true in
|
||||
|
|
@ -58,52 +58,16 @@ info: Try this to display the actual theorem instances:
|
|||
#guard_msgs in
|
||||
#grind_lint inspect Array.range_succ Array.range'_succ
|
||||
|
||||
/--
|
||||
info: instantiating `Array.extract_empty` triggers more than 100 additional `grind` theorem instantiations
|
||||
---
|
||||
info: instantiating `Array.filterMap_some` triggers more than 100 additional `grind` theorem instantiations
|
||||
---
|
||||
info: instantiating `Array.range_succ` triggers 22 additional `grind` theorem instantiations
|
||||
-/
|
||||
#guard_msgs in
|
||||
#grind_lint check (min := 20) (detailed := 200) in Array
|
||||
#grind_lint check (min := 20) in Array
|
||||
|
||||
#grind_lint skip Array.extract_empty -- `#grind_lint check` skips it from now on
|
||||
|
||||
/--
|
||||
info: instantiating `Array.filterMap_some` triggers more than 100 additional `grind` theorem instantiations
|
||||
---
|
||||
info: instantiating `Array.range_succ` triggers 22 additional `grind` theorem instantiations
|
||||
-/
|
||||
#guard_msgs in
|
||||
#grind_lint check (min := 20) (detailed := 200) in Array
|
||||
#grind_lint check (min := 20) in Array
|
||||
|
||||
/--
|
||||
info: instantiating `Array.filterMap_some` triggers more than 100 additional `grind` theorem instantiations
|
||||
---
|
||||
info: Array.filterMap_some
|
||||
[thm] instances
|
||||
[thm] Array.filterMap_filterMap ↦ 94
|
||||
[thm] Array.size_filterMap_le ↦ 5
|
||||
[thm] Array.filterMap_some ↦ 1
|
||||
---
|
||||
info: Try this to display the actual theorem instances:
|
||||
[apply] set_option trace.grind.ematch.instance true in
|
||||
#grind_lint inspect Array.filterMap_some
|
||||
-/
|
||||
#guard_msgs in
|
||||
#grind_lint inspect Array.filterMap_some
|
||||
|
||||
/--
|
||||
info: instantiating `Array.filterMap_some` triggers more than 100 additional `grind` theorem instantiations
|
||||
---
|
||||
info: Array.filterMap_some
|
||||
[thm] instances
|
||||
[thm] Array.filterMap_filterMap ↦ 94
|
||||
[thm] Array.size_filterMap_le ↦ 5
|
||||
[thm] Array.filterMap_some ↦ 1
|
||||
---
|
||||
info: instantiating `Array.range_succ` triggers 22 additional `grind` theorem instantiations
|
||||
-/
|
||||
#guard_msgs in
|
||||
#grind_lint check (min := 20) in module Init.Data.Array
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue