Skip to content

Commit eee58f4

Browse files
kim-emclaude
andauthored
fix: include term parameters in grind? suggestions (#11594)
This PR fixes `grind?` to include term parameters (like `[show P by tac]`) in its suggestions. Previously, these were being dropped because term arguments are stored in `extraFacts` and not tracked via E-matching like named lemmas. For example, `grind? [show False by exact h]` now correctly suggests `grind only [show False by exact h]` instead of just `grind only`. 🤖 Prepared with Claude Code Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent 756396a commit eee58f4

File tree

3 files changed

+45
-9
lines changed

3 files changed

+45
-9
lines changed

src/Lean/Elab/Tactic/Grind/Main.lean

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,22 +334,39 @@ def evalGrindTraceCore (stx : Syntax) (trace := true) (verbose := true) (useSorr
334334
let config ← elabGrindConfig configStx
335335
let config := { config with clean := false, trace, verbose, useSorry }
336336
let only := only.isSome
337-
let params := if let some params := params? then params.getElems else #[]
337+
let paramStxs := if let some params := params? then params.getElems else #[]
338+
-- Extract term parameters (non-ident params) to include in the suggestion.
339+
-- These are not tracked via E-matching, so we conservatively include them all.
340+
-- Ident params resolve to global declarations and are tracked via E-matching.
341+
-- Non-ident terms (like `show P by tac`) need to be preserved explicitly.
342+
let termParamStxs : Array Grind.TParam := paramStxs.filter fun p =>
343+
match p with
344+
| `(Parser.Tactic.grindParam| $[$_:grindMod]? $_:ident) => false
345+
| `(Parser.Tactic.grindParam| ! $[$_:grindMod]? $_:ident) => false
346+
| `(Parser.Tactic.grindParam| - $_:ident) => false
347+
| `(Parser.Tactic.grindParam| #$_:hexnum) => false
348+
| _ => true
338349
let mvarId ← getMainGoal
339-
let params ← mkGrindParams config only params mvarId
350+
let params ← mkGrindParams config only paramStxs mvarId
340351
Grind.withProtectedMCtx config.abstractProof mvarId fun mvarId' => do
341352
let (tacs, _) ← Grind.GrindTacticM.runAtGoal mvarId' params do
342353
let finish ← Grind.Action.mkFinish
343354
let goal :: _ ← Grind.getGoals
344-
| let tac ← `(tactic| grind only)
345-
return #[tac]
355+
| -- Goal was closed during initialization
356+
let configStx' := filterSuggestionsFromGrindConfig configStx
357+
if termParamStxs.isEmpty then
358+
let tac ← `(tactic| grind $configStx':optConfig only)
359+
return #[tac]
360+
else
361+
let tac ← `(tactic| grind $configStx':optConfig only [$termParamStxs,*])
362+
return #[tac]
346363
Grind.liftGrindM do
347364
-- **Note**: If we get failures when using the first suggestion, we should test is using `saved`
348365
-- let saved ← saveState
349366
match (← finish.run goal) with
350367
| .closed seq =>
351368
let configStx' := filterSuggestionsFromGrindConfig configStx
352-
let tacs ← Grind.mkGrindOnlyTactics configStx' seq
369+
let tacs ← Grind.mkGrindOnlyTactics configStx' seq termParamStxs
353370
let seq := Grind.Action.mkGrindSeq seq
354371
let tac ← `(tactic| grind $configStx':optConfig => $seq:grindSeq)
355372
let tacs := tacs.push tac

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Lean.Meta.Grind
1111
Given an auto-generated `grind` tactic script, collect params for
1212
single shot `finish` or top-level `grind` tactic.
1313
-/
14-
abbrev TParam := TSyntax ``Parser.Tactic.grindParam
14+
public abbrev TParam := TSyntax ``Parser.Tactic.grindParam
1515
abbrev TAnchor := TSyntax ``Parser.Tactic.anchor
1616

1717
namespace Collector
@@ -93,16 +93,20 @@ Given a `grind` tactic sequence, extracts parameters and builds a `grind only` t
9393
It returns at most two. The first tactic uses anchors to restrict the search if applicable.
9494
The second does not restrict the search using anchors. The second option is included only if there
9595
are anchors.
96+
97+
The `extraParams` are additional parameters (e.g., term arguments from the original `grind?` call)
98+
that should always be included in the suggestion.
9699
-/
97-
public def mkGrindOnlyTactics (cfg : TSyntax `Lean.Parser.Tactic.optConfig) (seq : List TGrind) : CoreM (Array (TSyntax `tactic)) := do
100+
public def mkGrindOnlyTactics (cfg : TSyntax `Lean.Parser.Tactic.optConfig) (seq : List TGrind)
101+
(extraParams : Array TParam := #[]) : CoreM (Array (TSyntax `tactic)) := do
98102
let (hasSorry, params, anchors) ← collectParamsCore seq
99103
if hasSorry then return #[]
100-
let allParams := params ++ anchors
104+
let allParams := params ++ anchors ++ extraParams
101105
let s₁ ← mkTac allParams
102106
if anchors.isEmpty then
103107
return #[s₁]
104108
else
105-
let s₂ ← mkTac params
109+
let s₂ ← mkTac (params ++ extraParams)
106110
return #[s₁, s₂]
107111
where
108112
mkTac (params : Array TParam) : CoreM (TSyntax `tactic) :=
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/-!
2+
# Test that `grind?` includes term parameters in its suggestion
3+
4+
When a user provides term arguments to `grind?`, they should be included
5+
in the suggestion even if they are not tracked via E-matching.
6+
-/
7+
8+
-- Test: Term argument should be included in suggestion
9+
-- The term `show False by exact h` is passed as argument and should appear in output
10+
/--
11+
info: Try this:
12+
[apply] grind only [show False by exact h]
13+
-/
14+
#guard_msgs in
15+
example (h : False) : False := by grind? [show False by exact h]

0 commit comments

Comments
 (0)