Skip to content

Commit c56f8b7

Browse files
committed
feat: restrinct local theorem instantiation using anchors.
1 parent 639d2e7 commit c56f8b7

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

src/Lean/Meta/Tactic/Grind/ForallProp.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Lean.Meta.Tactic.Grind.PropagatorAttr
1313
import Lean.Meta.Tactic.Grind.Propagate
1414
import Lean.Meta.Tactic.Grind.Internalize
1515
import Lean.Meta.Tactic.Grind.Simp
16+
import Lean.Meta.Tactic.Grind.Anchor
1617
import Lean.Meta.Tactic.Grind.EqResolution
1718
import Lean.Meta.Tactic.Grind.SynthInstance
1819
public section
@@ -74,6 +75,15 @@ private def mkEMatchTheoremWithKind'? (origin : Origin) (proof : Expr) (kind : E
7475
private def isNewPat (patternsFoundSoFar : Array (List Expr)) (thm' : EMatchTheorem) : Bool :=
7576
patternsFoundSoFar.all fun ps => thm'.patterns != ps
7677

78+
/--
79+
Returns `true`, if there are no anchor references restricting the search,
80+
or there is an anchor references `ref` s.t. `ref` matches `proof`.
81+
-/
82+
private def checkAnchorRefs (proof : Expr) : GrindM Bool := do
83+
let some anchorRefs ← getAnchorRefs | return true
84+
let anchor ← getAnchor (← inferType proof)
85+
return anchorRefs.any (·.matches anchor)
86+
7787
private def addLocalEMatchTheorems (e : Expr) : GoalM Unit := do
7888
let proof ← mkEqTrueProof e
7989
let origin ← if let some fvarId := isEqTrueHyp? proof then
@@ -82,6 +92,9 @@ private def addLocalEMatchTheorems (e : Expr) : GoalM Unit := do
8292
let idx ← modifyGet fun s => (s.ematch.nextThmIdx, { s with ematch.nextThmIdx := s.ematch.nextThmIdx + 1 })
8393
pure <| .local ((`local).appendIndexAfter idx)
8494
let proof := mkOfEqTrueCore e proof
95+
-- **Note**: Do we really need to restrict the instantiation of local theorems?
96+
-- **Note**: Should we distinguish anchors restricting case-splits and local theorems?
97+
unless (← checkAnchorRefs proof) do return ()
8598
let size := (← get).ematch.newThms.size
8699
let gen ← getGeneration e
87100
let mut patternsFoundSoFar := #[]

src/Lean/Meta/Tactic/Grind/Types.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,12 @@ def anchorPrefixToString (numDigits : Nat) (anchorPrefix : UInt64) : String :=
18961896
def anchorToString (numDigits : Nat) (anchor : UInt64) : String :=
18971897
anchorPrefixToString numDigits (anchor >>> (64 - 4*numDigits.toUInt64))
18981898

1899+
def AnchorRef.toString (anchorRef : AnchorRef) : String :=
1900+
anchorPrefixToString anchorRef.numDigits anchorRef.anchorPrefix
1901+
1902+
instance : ToString AnchorRef where
1903+
toString := AnchorRef.toString
1904+
18991905
/--
19001906
Returns activated `match`-declaration equations.
19011907
Recall that in tactics such as `instantiate only [...]`, `match`-declarations are always instantiated.

tests/lean/run/grind_finish_trace.lean

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,35 @@ example (f g : Int → Int) (x y z w : Int)
219219
fail_if_success grind [#23ad] -- not possible to solve using this set of anchors.
220220
set_option trace.grind.split true in
221221
grind [#23ad, #beb4] -- Only these two splits were performed.
222+
223+
/--
224+
trace: [grind.ematch.instance] h: f (f a) = f a
225+
[grind.ematch.instance] h: f (f (f a)) = f (f a)
226+
[grind.ematch.instance] h: f (f (f (f a))) = f (f (f a))
227+
[grind.ematch.instance] h_1: g (g (g b)) = g (g b)
228+
[grind.ematch.instance] h_1: g (g b) = g b
229+
-/
230+
#guard_msgs in
231+
example (f g : Int → Int)
232+
(_ : ∀ x, f (f x) = f x)
233+
(_ : ∀ x, g (g x) = g x)
234+
(a b : Int)
235+
(_ : g (g b) = b)
236+
: f (f (f a)) = f a := by
237+
set_option trace.grind.ematch.instance true in
238+
grind
239+
240+
/--
241+
trace: [grind.ematch.instance] h: f (f a) = f a
242+
[grind.ematch.instance] h: f (f (f a)) = f (f a)
243+
[grind.ematch.instance] h: f (f (f (f a))) = f (f (f a))
244+
-/
245+
#guard_msgs in
246+
example (f g : Int → Int)
247+
(_ : ∀ x, f (f x) = f x)
248+
(_ : ∀ x, g (g x) = g x)
249+
(a b : Int)
250+
(_ : g (g b) = b)
251+
: f (f (f a)) = f a := by
252+
set_option trace.grind.ematch.instance true in
253+
grind [#99cb]

0 commit comments

Comments
 (0)