fix: grind preprocessor (#10177)

This PR fixes a bug in the `grind` preprocessor exposed by #10160.

Closes #10160
This commit is contained in:
Leonardo de Moura 2025-08-29 16:37:52 -07:00 committed by GitHub
parent 50ddf85b07
commit 404b00a584
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 115 additions and 72 deletions

View file

@ -5,13 +5,13 @@ Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.Tactic.Grind.ProveEq
public import Lean.Meta.Tactic.Grind.Arith.CommRing.DenoteExpr
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.Arith.Linear.Util
public import Lean.Meta.Tactic.Grind.Arith.Linear.Var
import Lean.Meta.Tactic.Grind.Simp
import Lean.Meta.Tactic.Grind.Arith.CommRing.DenoteExpr
import Lean.Meta.Tactic.Grind.Arith.Linear.Var
import Lean.Meta.Tactic.Grind.Arith.CommRing.Functions
public section
namespace Lean.Meta.Grind.Arith.Linear
/-!
Helper functions for converting reified terms back into their denotations.

View file

@ -6,6 +6,7 @@ Authors: Leonardo de Moura
module
prelude
public import Lean.Meta.Tactic.Grind.Arith.Linear.Util
import Lean.Data.RArray
import Lean.Meta.Tactic.Grind.Arith.Util
import Lean.Meta.Tactic.Grind.Arith.Linear.ToExpr
import Lean.Meta.Tactic.Grind.Arith.Linear.DenoteExpr

View file

@ -4,15 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.Tactic.Util
public import Lean.Meta.Tactic.Cases
public import Lean.Meta.Match.MatcherApp
public import Lean.Meta.Tactic.Grind.MatchCond
import Lean.Meta.Tactic.Grind.Types
import Lean.Meta.Tactic.Cases
import Lean.Meta.Match.MatcherApp
import Lean.Meta.Tactic.Grind.MatchCond
import Lean.Meta.Tactic.Grind.Simp
public section
namespace Lean.Meta.Grind
/-- Returns `true` if `e` is of the form `∀ ..., _ = _ ... -> False` -/

View file

@ -7,10 +7,8 @@ module
prelude
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.ProveEq
import Lean.Meta.Tactic.Grind.Simp
public section
namespace Lean.Meta.Grind
private partial def propagateInjEqs (eqs : Expr) (proof : Expr) : GoalM Unit := do

View file

@ -7,6 +7,8 @@ module
prelude
public import Lean.Meta.Tactic.Grind.Types
import Lean.Meta.Tactic.Grind.Core
import Lean.Meta.Tactic.Grind.MatchDiscrOnly
import Lean.Meta.Tactic.Grind.ProveEq
import Lean.Meta.Tactic.Grind.SynthInstance
public section
namespace Lean.Meta.Grind

View file

@ -4,17 +4,17 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Grind.Lemmas
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.Internalize
public import Lean.Meta.Tactic.Grind.Simp
public import Lean.Meta.Tactic.Grind.EqResolution
public import Init.Grind.Propagator
import Init.Grind.Lemmas
import Init.Grind.Norm
import Lean.Meta.Tactic.Grind.Propagate
import Lean.Meta.Tactic.Grind.Internalize
import Lean.Meta.Tactic.Grind.Simp
import Lean.Meta.Tactic.Grind.EqResolution
import Lean.Meta.Tactic.Grind.SynthInstance
public section
namespace Lean.Meta.Grind
/--
If `parent` is a projection-application `proj_i c`,

View file

@ -4,22 +4,21 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Grind.Util
public import Init.Grind.Lemmas
public import Lean.Meta.LitValues
public import Lean.Meta.Match.MatcherInfo
public import Lean.Meta.Match.MatchEqsExt
public import Lean.Meta.Match.MatchEqs
public import Lean.Util.CollectLevelParams
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.Util
public import Lean.Meta.Tactic.Grind.Beta
public import Lean.Meta.Tactic.Grind.MatchCond
import Lean.Meta.LitValues
import Lean.Meta.Match.MatcherInfo
import Lean.Meta.Match.MatchEqsExt
import Lean.Meta.Match.MatchEqs
import Lean.Util.CollectLevelParams
import Lean.Meta.Tactic.Grind.Util
import Lean.Meta.Tactic.Grind.Beta
import Lean.Meta.Tactic.Grind.MatchCond
import Lean.Meta.Tactic.Grind.Simp
import Lean.Meta.Tactic.Grind.MarkNestedSubsingletons
public section
namespace Lean.Meta.Grind
@[extern "lean_grind_ac_internalize"] -- forward definition

View file

@ -4,20 +4,18 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Grind.Lemmas
public import Lean.Meta.Tactic.Assert
public import Lean.Meta.Tactic.Grind.Simp
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.Cases
public import Lean.Meta.Tactic.Grind.CasesMatch
public import Lean.Meta.Tactic.Grind.Injection
public import Lean.Meta.Tactic.Grind.Core
public import Lean.Meta.Tactic.Grind.SearchM
import Lean.Meta.Tactic.Assert
import Lean.Meta.Tactic.Apply
import Lean.Meta.Tactic.Grind.Simp
import Lean.Meta.Tactic.Grind.Cases
import Lean.Meta.Tactic.Grind.CasesMatch
import Lean.Meta.Tactic.Grind.Injection
import Lean.Meta.Tactic.Grind.Core
public section
namespace Lean.Meta.Grind
private inductive IntroResult where

View file

@ -4,13 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Init.Grind.Lemmas
public import Lean.Meta.Tactic.Util
public import Lean.Meta.Tactic.ExposeNames
public import Lean.Meta.Tactic.Simp.Diagnostics
public import Lean.Meta.Tactic.Grind.Split -- TODO: not minimal yet
public import Lean.Meta.Tactic.Grind.Types
import Init.Grind.Lemmas
import Lean.Meta.Tactic.ExposeNames
import Lean.Meta.Tactic.Simp.Diagnostics
import Lean.Meta.Tactic.Grind.Split
import Lean.Meta.Tactic.Grind.RevertAll
import Lean.Meta.Tactic.Grind.PropagatorAttr
import Lean.Meta.Tactic.Grind.Proj
@ -24,9 +24,8 @@ import Lean.Meta.Tactic.Grind.SimpUtil
import Lean.Meta.Tactic.Grind.Cases
import Lean.Meta.Tactic.Grind.LawfulEqCmp
import Lean.Meta.Tactic.Grind.ReflCmp
import Lean.Meta.Tactic.Grind.PP
public section
namespace Lean.Meta.Grind
structure Params where

View file

@ -7,18 +7,11 @@ module
prelude
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.Simp
import Lean.Meta.Tactic.Grind.Simp
public section
namespace Lean.Meta.Grind
/--
A lighter version of `preprocess` which produces a definitionally equal term,
but ensures assumptions made by `grind` are satisfied.
-/
def preprocessLight (e : Expr) : GoalM Expr := do
shareCommon (← canon (← normalizeLevels (← foldProjs (← eraseIrrelevantMData (← markNestedSubsingletons (← unfoldReducible e))))))
/--
If `e` has not been internalized yet, instantiate metavariables, unfold reducible, canonicalize,
and internalize the result.

View file

@ -6,12 +6,12 @@ Authors: Leonardo de Moura
module
prelude
public import Init.Grind.Lemmas
public import Lean.Meta.Tactic.Assert
public import Lean.Meta.Tactic.Simp.Main
public import Lean.Meta.Tactic.Grind.Util
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.MatchDiscrOnly
public import Lean.Meta.Tactic.Grind.MarkNestedSubsingletons
import Lean.Meta.Tactic.Assert
import Lean.Meta.Tactic.Grind.Util
import Lean.Meta.Tactic.Grind.MatchDiscrOnly
import Lean.Meta.Tactic.Grind.MarkNestedSubsingletons
public section
namespace Lean.Meta.Grind
@ -50,6 +50,9 @@ def preprocess (e : Expr) : GoalM Simp.Result := do
let e ← instantiateMVars e
let r ← simpCore e
let e' := r.expr
-- Remark: `simpCore` unfolds reducible constants, but it does not consistently visit all possible subterms.
-- So, we must use the following `unfoldReducible` step. It is non-op in most cases
let e' ← unfoldReducible e'
let e' ← abstractNestedProofs e'
let e' ← markNestedSubsingletons e'
let e' ← eraseIrrelevantMData e'
@ -83,4 +86,11 @@ def pushNewFact (proof : Expr) (generation : Nat := 0) : GoalM Unit := do
trace[grind.debug.pushNewFact] "{prop}"
pushNewFact' prop proof generation
/--
A lighter version of `preprocess` which produces a definitionally equal term,
but ensures assumptions made by `grind` are satisfied.
-/
def preprocessLight (e : Expr) : GoalM Expr := do
shareCommon (← canon (← normalizeLevels (← foldProjs (← eraseIrrelevantMData (← markNestedSubsingletons (← unfoldReducible e))))))
end Lean.Meta.Grind

View file

@ -4,16 +4,15 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.Tactic.Grind.Split
public import Lean.Meta.Tactic.Grind.EMatch
public import Lean.Meta.Tactic.Grind.Arith
public import Lean.Meta.Tactic.Grind.Lookahead
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.SearchM
import Lean.Meta.Tactic.Grind.Split
import Lean.Meta.Tactic.Grind.EMatch
import Lean.Meta.Tactic.Grind.Arith
import Lean.Meta.Tactic.Grind.Lookahead
import Lean.Meta.Tactic.Grind.Intro
public section
namespace Lean.Meta.Grind
def tryFallback : GoalM Bool := do
(← getMethods).fallback

View file

@ -4,16 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
public import Lean.Meta.Tactic.Grind.Types
public import Lean.Meta.Tactic.Grind.Intro
public import Lean.Meta.Tactic.Grind.Cases
public import Lean.Meta.Tactic.Grind.CasesMatch
public import Lean.Meta.Tactic.Grind.SearchM
import Lean.Meta.Tactic.Grind.Intro
import Lean.Meta.Tactic.Grind.Cases
import Lean.Meta.Tactic.Grind.CasesMatch
import Lean.Meta.Tactic.Grind.Internalize
public section
namespace Lean.Meta.Grind
inductive SplitStatus where

View file

@ -0,0 +1,47 @@
structure PreInt where
minuend : Nat
subtrahend : Nat
/-- Definition 4.1.1 -/
instance PreInt.instSetoid : Setoid PreInt where
r a b := a.minuend + b.subtrahend = b.minuend + a.subtrahend
iseqv := {
refl := by grind
symm := by grind
trans := by grind
}
abbrev MyInt := Quotient PreInt.instSetoid
abbrev MyInt.formalDiff (a b : Nat) : MyInt := Quotient.mk PreInt.instSetoid ⟨ a, b ⟩
theorem MyInt.eq (a b c d : Nat) : formalDiff a b = formalDiff c d ↔ a + d = c + b :=
⟨ Quotient.exact, by intro h; exact Quotient.sound h ⟩
instance MyInt.instOfNat {n : Nat} : OfNat MyInt n where
ofNat := formalDiff n 0
instance MyInt.instNatCast : NatCast MyInt where
natCast n := formalDiff n 0
theorem MyInt.natCast_eq (n : Nat) : (n : MyInt) = formalDiff n 0 := rfl
theorem MyInt.natCast_inj (n m : Nat) :
(n : MyInt) = (m : MyInt) ↔ n = m := by
rw [natCast_eq, natCast_eq, eq]
grind
example (n m : Nat) : (n : MyInt) = (m : MyInt) ↔ n = m := by
grind [MyInt.natCast_eq, MyInt.eq]
@[grind]
theorem MyInt.eq_0_of_cast_eq_0 (n : Nat) (h : (n : MyInt) = 0) : n = 0 := by
rw [show (0 : MyInt) = ((0 : Nat) : MyInt) by rfl] at h
rwa [natCast_inj] at h
theorem MyInt.pos_iff_gt_0 {a : MyInt} : (∃ (n:Nat), n > 0 ∧ a = n) → a ≠ 0 := by
intro ⟨ w, hw ⟩ h
grind
example {a : MyInt} : (∃ (n:Nat), n > 0 ∧ a = n) → a ≠ 0 := by
grind