Commit f1fc7ad 1 parent 22a9cd0 commit f1fc7ad Copy full SHA for f1fc7ad
File tree 3 files changed +64
-2
lines changed
src/Lean/Meta/Tactic/Grind
3 files changed +64
-2
lines changed Original file line number Diff line number Diff line change @@ -74,6 +74,14 @@ private def checkIffStatus (e a b : Expr) : GoalM CaseSplitStatus := do
74
74
else
75
75
return .notReady
76
76
77
+ /-- Returns `true` is `c` is congruent to a case-split that was already performed. -/
78
+ private def isCongrToPrevSplit (c : Expr) : GoalM Bool := do
79
+ (← get).resolvedSplits.foldM (init := false ) fun flag { expr := c' } => do
80
+ if flag then
81
+ return true
82
+ else
83
+ return isCongruent (← get).enodes c c'
84
+
77
85
private def checkCaseSplitStatus (e : Expr) : GoalM CaseSplitStatus := do
78
86
match_expr e with
79
87
| Or a b => checkDisjunctStatus e a b
@@ -85,6 +93,8 @@ private def checkCaseSplitStatus (e : Expr) : GoalM CaseSplitStatus := do
85
93
if (← isResolvedCaseSplit e) then
86
94
trace[grind.debug.split] "split resolved: {e}"
87
95
return .resolved
96
+ if (← isCongrToPrevSplit e) then
97
+ return .resolved
88
98
if let some info := isMatcherAppCore? (← getEnv) e then
89
99
return .ready info.numAlts
90
100
let .const declName .. := e.getAppFn | unreachable!
@@ -163,6 +173,7 @@ def splitNext : GrindTactic := fun goal => do
163
173
| return none
164
174
let gen ← getGeneration c
165
175
let genNew := if numCases > 1 || isRec then gen+1 else gen
176
+ markCaseSplitAsResolved c
166
177
trace_goal[grind.split] "{c}, generation: {gen}"
167
178
let mvarIds ← if (← isMatcherApp c) then
168
179
casesMatch (← get).mvarId c
Original file line number Diff line number Diff line change @@ -378,7 +378,7 @@ structure Goal where
378
378
splitCandidates : List Expr := []
379
379
/-- Number of splits performed to get to this goal. -/
380
380
numSplits : Nat := 0
381
- /-- Case-splits that do not have to be performed anymore. -/
381
+ /-- Case-splits that have already been performed, or that do not have to be performed anymore. -/
382
382
resolvedSplits : PHashSet ENodeKey := {}
383
383
/-- Next local E-match theorem idx. -/
384
384
nextThmIdx : Nat := 0
@@ -879,7 +879,8 @@ def isResolvedCaseSplit (e : Expr) : GoalM Bool :=
879
879
880
880
/--
881
881
Mark `e` as a case-split that does not need to be performed anymore.
882
- Remark: we currently use this feature to disable `match`-case-splits
882
+ Remark: we currently use this feature to disable `match`-case-splits.
883
+ Remark: we also use this feature to record the case-splits that have already been performed.
883
884
-/
884
885
def markCaseSplitAsResolved (e : Expr) : GoalM Unit := do
885
886
unless (← isResolvedCaseSplit e) do
Original file line number Diff line number Diff line change
1
+ variable (d : Nat) in
2
+ inductive X : Nat → Prop
3
+ | f {s : Nat} : X s
4
+ | g {s : Nat} : X d → X s
5
+
6
+ /--
7
+ error: `grind` failed
8
+ case grind.1
9
+ c : Nat
10
+ q : X c 0
11
+ s : Nat
12
+ h✝ : 0 = s
13
+ h : HEq ⋯ ⋯
14
+ ⊢ False
15
+ [ grind ] Diagnostics
16
+ [ facts ] Asserted facts
17
+ [ prop ] X c 0
18
+ [ prop ] 0 = s
19
+ [ prop ] HEq ⋯ ⋯
20
+ [ eqc ] True propositions
21
+ [ prop ] X c 0
22
+ [ prop ] X c s
23
+ [ eqc ] Equivalence classes
24
+ [ eqc ] {s, 0}
25
+ case grind.2
26
+ c : Nat
27
+ q : X c 0
28
+ s : Nat
29
+ a✝¹ a✝ : X c c
30
+ h✝ : 0 = s
31
+ h : HEq ⋯ ⋯
32
+ ⊢ False
33
+ [ grind ] Diagnostics
34
+ [ facts ] Asserted facts
35
+ [ prop ] X c 0
36
+ [ prop ] X c c
37
+ [ prop ] 0 = s
38
+ [ prop ] HEq ⋯ ⋯
39
+ [ eqc ] True propositions
40
+ [ prop ] X c 0
41
+ [ prop ] X c c
42
+ [ prop ] X c s
43
+ [ eqc ] Equivalence classes
44
+ [ eqc ] {s, 0}
45
+ [ issues ] Issues
46
+ [ issue ] this goal was not fully processed due to previous failures, threshold: `(failures := 1)`
47
+ -/
48
+ #guard_msgs (error) in
49
+ example {c : Nat} (q : X c 0 ) : False := by
50
+ grind
You can’t perform that action at this time.
0 commit comments