Skip to content

Commit 9263a6c

Browse files
authored
feat: add Grind.Config.reducible (#11480)
This PR adds the `grind` option `reducible` (default: `true`). When enabled, definitional equality tests expand only declarations marked as `@[reducible]`. Use `grind -reducible` to allow expansion of non-reducible declarations during definitional equality tests. This option affects only definitional equality; the canonicalizer and theorem pattern internalization always unfold reducible declarations regardless of this setting.
1 parent edcef51 commit 9263a6c

File tree

6 files changed

+75
-8
lines changed

6 files changed

+75
-8
lines changed

src/Init/Grind/Config.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,15 @@ structure Config where
202202
```
203203
-/
204204
funCC := true
205+
/--
206+
When `true`, use reducible transparency when trying to close goals.
207+
In this setting, only declarations marked with `@[reducible]` are unfolded during
208+
definitional equality tests.
209+
210+
This option does not affect the canonicalizer or how theorem patterns are internalized;
211+
reducible declarations are always unfolded in those contexts.
212+
-/
213+
reducible := true
205214
deriving Inhabited, BEq
206215

207216
/--

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,12 @@ def tryTactic (tac : GrindTacticM α) : GrindTacticM Bool := do
283283
open Grind
284284

285285
/-
286-
**Note**: Recall that `grind` uses `Reducible` setting to avoid expensive definitionally equality tests.
286+
**Note**: Recall that `grind` uses the reducibility specified at `Config.reducible`
287287
-/
288-
def liftGrindM (k : GrindM α) : GrindTacticM α := withReducible do
288+
def liftGrindM (k : GrindM α) : GrindTacticM α := do
289289
let ctx ← read
290290
let s ← get
291-
let (a, state) ← liftMetaM <| k ctx.methods.toMethodsRef ctx.ctx |>.run s.state
291+
let (a, state) ← liftMetaM <| (Grind.withGTransparency k) ctx.methods.toMethodsRef ctx.ctx |>.run s.state
292292
modify fun s => { s with state }
293293
return a
294294

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,9 @@ where
500500
-- which is not reducible.
501501
proof := mkExpectedPropHint proof prop
502502
/-
503-
**Note**: Must restore `reducible` setting because with use `withDefault` at `instantiateTheorem`.
503+
**Note**: Restores grind transparency setting because with use `withDefault` at `instantiateTheorem`.
504504
-/
505-
withReducible do
505+
withGTransparency do
506506
addTheoremInstance thm proof prop (generation+1) guards
507507

508508
private def synthesizeInsts (mvars : Array Expr) (bis : Array BinderInfo) : OptionT M Unit := do

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def mkResult (params : Params) (failure? : Option Goal) : GrindM Result := do
262262
return { failure?, issues, config := params.config, counters, simp, splitDiags }
263263

264264
def GrindM.runAtGoal (mvarId : MVarId) (params : Params) (k : Goal → GrindM α) (evalTactic? : Option EvalTactic := none) : MetaM α := do
265-
let go : GrindM α := withReducible do
265+
let go : GrindM α := withGTransparency do
266266
let goal ← initCore mvarId params
267267
k goal
268268
go.run params (evalTactic? := evalTactic?)

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,14 @@ def withSplitSource [MonadControlT GrindM m] [Monad m] (splitSource : SplitSourc
298298
def getConfig : GrindM Grind.Config :=
299299
return (← readThe Context).config
300300

301+
/--
302+
Runs `k` with the transparency setting specified by `Config.reducible`.
303+
Uses reducible transparency if `reducible` is `true`, otherwise default transparency.
304+
-/
305+
abbrev withGTransparency [MonadControlT MetaM n] [MonadLiftT GrindM n] [Monad n] (k : n α) : n α := do
306+
let m := if (← getConfig).reducible then .reducible else .default
307+
withTransparency m k
308+
301309
/-- Returns the internalized `True` constant. -/
302310
def getTrueExpr : GrindM Expr := do
303311
return (← readThe Context).trueExpr
@@ -1025,7 +1033,7 @@ def markTheoremInstance (proof : Expr) (assignment : Array Expr) : GoalM Bool :=
10251033
/-- Adds a new fact `prop` with proof `proof` to the queue for preprocessing and the assertion. -/
10261034
def addNewRawFact (proof : Expr) (prop : Expr) (generation : Nat) (splitSource : SplitSource) : GoalM Unit := do
10271035
if grind.debug.get (← getOptions) then
1028-
unless (← withReducible <| isDefEq (← inferType proof) prop) do
1036+
unless (← withGTransparency <| isDefEq (← inferType proof) prop) do
10291037
throwError "`grind` internal error, trying to assert{indentExpr prop}\n\
10301038
with proof{indentExpr proof}\nwhich has type{indentExpr (← inferType proof)}\n\
10311039
which is not definitionally equal with `reducible` transparency setting}"
@@ -1182,7 +1190,7 @@ def pushEqCore (lhs rhs proof : Expr) (isHEq : Bool) : GoalM Unit := do
11821190
throwError "`grind` internal error, rhs of new equality has not been internalized{indentExpr rhs}"
11831191
if proof != congrPlaceholderProof && proof != eqCongrSymmPlaceholderProof then
11841192
let expectedType ← if isHEq then mkHEq lhs rhs else mkEq lhs rhs
1185-
unless (← withReducible <| isDefEq (← inferType proof) expectedType) do
1193+
unless (← withGTransparency <| isDefEq (← inferType proof) expectedType) do
11861194
throwError "`grind` internal error, trying to assert equality{indentExpr expectedType}\n\
11871195
with proof{indentExpr proof}\nwhich has type{indentExpr (← inferType proof)}\n\
11881196
which is not definitionally equal with `reducible` transparency setting}"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
variable {α β γ : Type}
2+
3+
structure Equiv (α β : Type) where
4+
toFun : α → β
5+
invFun : β → α
6+
7+
infixl:25 "" => Equiv
8+
9+
namespace Equiv
10+
11+
instance : CoeFun (α ≃ β) (fun _ => α → β) := ⟨toFun⟩
12+
13+
@[ext, grind ext] theorem ext {f g : Equiv α β} (H : ∀ x, f x = g x) : f = g := sorry
14+
15+
theorem congr_fun {f g : Equiv α β} (h : f = g) (x : α) : f x = g x := by rw [h]
16+
17+
def symm (e : α ≃ β) : β ≃ α := ⟨e.invFun, e.toFun⟩
18+
19+
def trans (e₁ : α ≃ β) (e₂ : β ≃ γ) : α ≃ γ := ⟨e₂ ∘ e₁, e₁.symm ∘ e₂.symm⟩
20+
21+
def sigmaCongrRight {α : Type} {β₁ β₂ : α → Type} (F : ∀ a, β₁ a ≃ β₂ a) : (Σ a, β₁ a) ≃ Σ a, β₂ a where
22+
toFun a := ⟨a.1, F a.1 a.2
23+
invFun a := ⟨a.1, (F a.1).symm a.2
24+
25+
def sigmaEquivProd (α β : Type) : (Σ _ : α, β) ≃ α × β where
26+
toFun a := ⟨a.1, a.2
27+
invFun a := ⟨a.1, a.2
28+
29+
end Equiv
30+
31+
variable {α₁ β₁ β₂ : Type} (e : α₁ → β₁ ≃ β₂)
32+
33+
def prodCongrRight : α₁ × β₁ ≃ α₁ × β₂ where
34+
toFun ab := ⟨ab.1, e ab.1 ab.2
35+
invFun ab := ⟨ab.1, (e ab.1).symm ab.2
36+
37+
example :
38+
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
39+
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
40+
grind -reducible only [Equiv.congr_fun]
41+
42+
example :
43+
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
44+
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
45+
grind -reducible only => finish only [Equiv.congr_fun]
46+
47+
example :
48+
(Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
49+
= (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
50+
grind -reducible => cases #5103 <;> instantiate only [Equiv.congr_fun]

0 commit comments

Comments
 (0)