Compare commits

...

1 Commits

Author SHA1 Message Date
Leonardo de Moura
7dad41b588 fix: grind internalization
This PR fixes a local declaration internalization in `grind` that was
exposed when using `grind -revert`. This bug was affecting a `grind`
proof in Mathlib.
2025-11-21 20:09:41 -08:00
3 changed files with 56 additions and 10 deletions

View File

@@ -215,16 +215,7 @@ private def addHypotheses (goal : Goal) : GrindM Goal := GoalM.run' goal do
| none => add r.expr localDecl.toExpr
| some h => add r.expr <| mkApp4 (mkConst ``Eq.mp [0]) type r.expr h localDecl.toExpr
else
/-
**Note**: We must internalize local variables because their types may be empty, and may not be
referenced anywhere else. Example:
```
example (a : { x : Int // x < 0 ∧ x > 0 }) : False := by grind
```
-/
let e shareCommon localDecl.toExpr
internalize e 0
processNewFacts
internalizeLocalDecl localDecl
private def initCore (mvarId : MVarId) (params : Params) : GrindM Goal := do
/-

View File

@@ -1288,6 +1288,23 @@ opaque internalize (e : Expr) (generation : Nat) (parent? : Option Expr := none)
@[extern "lean_grind_process_new_facts"]
opaque processNewFacts : GoalM Unit
/--
Internalizes a local declaration which is not a proposition.
**Note**: We must internalize local variables because their types may be empty, and may not be
referenced anywhere else. Example:
```
example (a : { x : Int // x < 0 ∧ x > 0 }) : False := by grind
```
`etaStruct` may also be applicable.
-/
def internalizeLocalDecl (localDecl : LocalDecl) : GoalM Unit := do
let e shareCommon localDecl.toExpr
internalize e 0
/-
**Note**: `internalize` may add new facts (e.g., `etaStruct` equality)
-/
processNewFacts
/--
Returns a proof that `a = b` if they have the same type. Otherwise, returns a proof of `a ≍ b`.
It assumes `a` and `b` are in the same equivalence class.

View File

@@ -0,0 +1,38 @@
namespace List
/-
This example exposed a bug in the `grind` internalizer when `grind -revert`
is used.
-/
variable {α : Type} {β : α Type}
def keys : List (Sigma β) List α :=
map Sigma.fst
@[grind =]
theorem keys_cons {s} {l : List (Sigma β)} : (s :: l).keys = s.1 :: l.keys :=
rfl
variable [DecidableEq α]
def dlookup (a : α) : List (Sigma β) Option (β a)
| [] => none
| a', b :: l => if h : a' = a then some (Eq.recOn h b) else dlookup a l
@[grind =]
theorem dlookup_cons_eq (l) (a : α) (b : β a) : dlookup a (a, b :: l) = some b :=
dif_pos rfl
@[grind =]
theorem dlookup_cons_ne (l) {a} : s : Sigma β, a s.1 dlookup a (s :: l) = dlookup a l
| _, _, h => dif_neg h.symm
@[grind =]
theorem dlookup_isSome {a : α} {l : List (Sigma β)} : (dlookup a l).isSome a l.keys := by
induction l with
| nil => sorry
| cons s _ _ =>
by_cases a = s.fst
· grind
· sorry