Skip to content

Commit 1c1bd8e

Browse files
authored
fix: handle dot notation on local variables in grind parameters (#11573)
This PR fixes `grind` rejecting dot notation terms, mistaking them for local hypotheses. When a grind parameter like `n.triv` is given, where `n` is a local variable and `triv` is a theorem that takes `n` as an argument (so `n.triv` means `Nat.triv n`), grind was incorrectly rejecting it with "redundant parameter" because it detected that the identifier resolved to a local variable via `resolveLocalName`. The fix checks if `resolveLocalName` returns field projections (non-empty list), indicating dot notation. In that case, we process the parameter as a term expression to let elaboration resolve the dot notation properly, rather than trying to resolve it as a global constant name. ### Minimal reproducer ```lean theorem Nat.triv (n : Nat) : n = n := rfl example (n : Nat) : n = n := by grind [n.triv] -- Previously: "redundant parameter `n.triv`" ``` This also fixes the issue where `grind [x.exp_pos]` was rejected even though `x.exp_pos` elaborates to `Real.exp_pos x`, a valid theorem application. 🤖 Prepared with Claude Code
1 parent a20e029 commit 1c1bd8e

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,17 @@ public def elabGrindParams (params : Grind.Params) (ps : TSyntaxArray ``Parser.T
231231
else
232232
params := { params with ematch := (← params.ematch.eraseDecl declName) }
233233
| `(Parser.Tactic.grindParam| $[$mod?:grindMod]? $id:ident) =>
234-
params ← processParam params p mod? id (minIndexable := false) (only := only) (incremental := incremental)
234+
-- Check if this is dot notation on a local variable (e.g., `n.triv` for `Nat.triv n`).
235+
-- If so, process as term to let elaboration resolve the dot notation properly.
236+
if let some (_, _ :: _) := (← resolveLocalName id.getId) then
237+
params ← processTermParam params p mod? id (minIndexable := false)
238+
else
239+
params ← processParam params p mod? id (minIndexable := false) (only := only) (incremental := incremental)
235240
| `(Parser.Tactic.grindParam| ! $[$mod?:grindMod]? $id:ident) =>
236-
params ← processParam params p mod? id (minIndexable := true) (only := only) (incremental := incremental)
241+
if let some (_, _ :: _) := (← resolveLocalName id.getId) then
242+
params ← processTermParam params p mod? id (minIndexable := true)
243+
else
244+
params ← processParam params p mod? id (minIndexable := true) (only := only) (incremental := incremental)
237245
| `(Parser.Tactic.grindParam| $[$mod?:grindMod]? $e:term) =>
238246
params ← processTermParam params p mod? e (minIndexable := false)
239247
| `(Parser.Tactic.grindParam| ! $[$mod?:grindMod]? $e:term) =>

tests/lean/run/grind_local_hyps.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,10 @@ example : 0 = 0 := by
3838
example : 0 = 0 := by
3939
have h : 1 = 1 := rfl
4040
grind only [h]
41+
42+
-- Checks that dot notation on a local variable for a global theorem is accepted.
43+
-- `n.triv` means `Nat.triv n`, not a local hypothesis.
44+
theorem Nat.triv (n : Nat) : n = n := rfl
45+
46+
example (n : Nat) : n = n := by
47+
grind [n.triv]

0 commit comments

Comments
 (0)