| set_option linter.unusedSimpArgs false | |
| axiom testSorry : α | |
| opaque a : Nat | |
| opaque b : Nat | |
| theorem ab : a = b := testSorry | |
| theorem ba : b = a := testSorry | |
| theorem aa : a = id a := testSorry | |
| /-- | |
| warning: Possibly looping simp theorem: `aa` | |
| Note: Possibly caused by: `id` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : id a = 23 := by simp -failIfUnchanged only [aa, id] | |
| -- also simp_all | |
| /-- | |
| warning: Possibly looping simp theorem: `aa` | |
| Note: Possibly caused by: `id` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : id a = 23 := by simp_all -failIfUnchanged only [aa, id] | |
| -- Other exceptions do not trigger the loop check | |
| /-- | |
| error: unsolved goals | |
| ⊢ b = 23 | |
| -/ | |
| #guard_msgs in | |
| example : id b = 23 := by simp -failIfUnchanged only [aa, id] | |
| /-- | |
| warning: Possibly looping simp theorem: `aa` | |
| Note: Possibly caused by: `id` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| Note: This linter can be disabled with `set_option linter.loopingSimpArgs false` | |
| --- | |
| error: unsolved goals | |
| ⊢ b = 23 | |
| -/ | |
| #guard_msgs in | |
| set_option linter.loopingSimpArgs true in | |
| example : id b = 23 := by simp -failIfUnchanged only [aa, id] | |
| /-- error: `simp` made no progress -/ | |
| #guard_msgs in | |
| example : b = 23 := by simp only [aa, id] | |
| /-- | |
| warning: Possibly looping simp theorem: `ab` | |
| Note: Possibly caused by: `ba` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `ba` | |
| Note: Possibly caused by: `ab` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : a = 23 := by simp -failIfUnchanged [ab, ba] | |
| /-- | |
| warning: Possibly looping simp theorem: `ab` | |
| Note: Possibly caused by: `ba` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `ba` | |
| Note: Possibly caused by: `ab` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : a = 2*b := by simp -failIfUnchanged [ab, ba] | |
| /-- | |
| warning: Possibly looping simp theorem: `← ab` | |
| Note: Possibly caused by: `← ba` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `← ba` | |
| Note: Possibly caused by: `← ab` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : a = 23 := by simp -failIfUnchanged [← ab, ← ba] | |
| -- Local theorems are not checked for loops, | |
| -- but are still applied when checking other rules | |
| /-- | |
| warning: Possibly looping simp theorem: `ab` | |
| Note: Possibly caused by: `h` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example (h : b = a) : a = 23 := by simp -failIfUnchanged [ab, h] | |
| /-! Examples from the original RFC -/ | |
| variable (P : Nat → Prop) | |
| /-- | |
| warning: Possibly looping simp theorem: `Nat.add_assoc` | |
| Note: Possibly caused by: `(Nat.add_assoc _ _ _).symm` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `(Nat.add_assoc _ _ _).symm` | |
| Note: Possibly caused by: `Nat.add_assoc` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example (a b c : Nat) : P (a + b + c) := by simp [Nat.add_assoc, (Nat.add_assoc _ _ _).symm] | |
| inductive Tree (α : Type) where | node : α → List (Tree α) → Tree α | |
| def Tree.children : Tree α → List (Tree α) | .node _ ts => ts | |
| def Tree.size (t : Tree α) := 1 + List.sum (t.children.attach.map (fun ⟨c,_⟩ => c.size)) | |
| decreasing_by simp_wf; cases t; simp_all [Tree.children]; decreasing_trivial | |
| /-- | |
| warning: Possibly looping simp theorem: `Tree.size.eq_1` | |
| Note: Possibly caused by: `Tree.size` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example (t : Tree α) : 0 < t.size := by simp [Tree.size] | |
| /-- | |
| Identifiyng looping theorems by their origin is not enough, | |
| as the elements of conjunctions would clash, as shown by these: | |
| (The error message isn't great yet, but it's a corner case) | |
| -/ | |
| theorem b1ab : b = 1 ∧ a = b := testSorry | |
| theorem baab : b = a ∧ a = b := testSorry | |
| /-- | |
| error: unsolved goals | |
| P : Nat → Prop | |
| ⊢ 1 > 0 | |
| -/ | |
| #guard_msgs in | |
| example : a > 0 := by simp only [b1ab] | |
| /-- | |
| warning: Possibly looping simp theorem: `baab` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `baab` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : a > 0 := by simp only [baab] | |
| -- Same, with local theorems (should we ever support them): | |
| /-- | |
| error: unsolved goals | |
| P : Nat → Prop | |
| a b : Nat | |
| h1 : b = 1 ∧ a = b | |
| h2 : 1 > 0 | |
| ⊢ True | |
| -/ | |
| #guard_msgs in | |
| example | |
| (a b : Nat) | |
| (h1 : b = 1 ∧ a = b ) | |
| (h2 : a > 0) : True := by | |
| simp only [h1] at h2 | |
| /-! | |
| Unfolding should not confuse it. | |
| (Error message is not optimal as it does not mention the unfolded definition.) | |
| -/ | |
| def c := a | |
| def ac : a = c := rfl | |
| def ca : c = a := rfl | |
| def d := c | |
| def dc : d = c := rfl | |
| /-- | |
| warning: Possibly looping simp theorem: `c.eq_1` | |
| Note: Possibly caused by: `ac` and `c` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `ac` | |
| Note: Possibly caused by: `c` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : c > 0 := by simp only [c, ac] | |
| /-- | |
| warning: Possibly looping simp theorem: `dc` | |
| Note: Possibly caused by: `c` and `ac` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `c.eq_1` | |
| Note: Possibly caused by: `ac` and `c` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `ac` | |
| Note: Possibly caused by: `c` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : d > 0 := by simp only [dc, c, ac] | |
| /-- | |
| warning: Possibly looping simp theorem: `c.eq_1` | |
| Note: Possibly caused by: `ac` and `c` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| warning: Possibly looping simp theorem: `ac` | |
| Note: Possibly caused by: `c` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : a > 0 := by simp only [c, ac] | |
| example (h : c = 1) : d > 0 := by simp only [dc, h, ca, ac, Nat.one_pos] | |
| /-! | |
| Simp? does not print the warnings for now. Let’s see if users find that helpful or confusing. | |
| -/ | |
| /-- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : d > 0 := by simp? only [dc, ca, ac]; exact testSorry | |
| /-! | |
| But we can turn it on: | |
| -/ | |
| set_option linter.loopingSimpArgs true in | |
| /-- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : d > 0 := by simp? only [dc, ca, ac]; exact testSorry | |
| /-- | |
| info: Try this: | |
| [apply] simp only [dc, h, Nat.one_pos] | |
| -/ | |
| #guard_msgs in | |
| example (h : c = 1) : d > 0 := by simp? only [dc, h, ca, ac, Nat.one_pos] | |
| /-! An example where a second rewrite rules makes the looping rule looping, | |
| without being itself looping. | |
| -/ | |
| opaque f : Nat → Nat | |
| theorem fbfa : f b = f a := testSorry | |
| theorem fbffa : f b = f (f a) := testSorry | |
| -- This one doesn't actually trigger because `simpLoop` does not recurse when | |
| -- the expression is the same after `post`. Also see issue #8864 | |
| /-- | |
| error: unsolved goals | |
| P : Nat → Prop | |
| ⊢ 0 < f a | |
| -/ | |
| #guard_msgs in | |
| example : 0 < f a := by simp -failIfUnchanged [fbfa, ab] | |
| /-- | |
| warning: Possibly looping simp theorem: `fbffa` | |
| Note: Possibly caused by: `ab` | |
| Hint: You can disable a simp theorem from the default simp set by passing `- theoremName` to `simp`. | |
| --- | |
| error: Tactic `simp` failed with a nested error: | |
| maximum recursion depth has been reached | |
| use `set_option maxRecDepth <num>` to increase limit | |
| use `set_option diagnostics true` to get diagnostic information | |
| -/ | |
| #guard_msgs in | |
| example : 0 < f a := by simp -failIfUnchanged [fbffa, ab] |