lean4-htt/tests/lean/run/grind_implies.lean
Leonardo de Moura 61186629d6
feat: grind -revert (#11248)
This PR implements the option `revert`, which is set to `false` by
default. To recover the old `grind` behavior, you should use `grind
+revert`. Previously, `grind` used the `RevSimpIntro` idiom, i.e., it
would revert all hypotheses and then re-introduce them while simplifying
and applying eager `cases`. This idiom created several problems:

* Users reported that `grind` would include unnecessary parameters. See
[here](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Grind.20aggressively.20includes.20local.20hypotheses.2E/near/554887715).
* Unnecessary section variables were also being introduced. See the new
test contributed by Sebastian Graf.
* Finally, it prevented us from supporting arbitrary parameters as we do
in `simp`. In `simp`, I implemented a mechanism that simulates local
universe-polymorphic theorems, but this approach could not be used in
`grind` because there is no mechanism for reverting (and re-introducing)
local universe-polymorphic theorems. Adding such a mechanism would
require substantial work: I would need to modify the local context
object. I considered maintaining a substitution from the original
variables to the new ones, but this is also tricky, because the mapping
would have to be stored in the `grind` goal objects, and it is not just
a simple mapping. After reverting everything, I would need to keep a
sequence of original variables that must be added to the mapping as we
re-introduce them, but eager case splits complicate this quite a bit.
The whole approach felt overly messy.

The new behavior `grind -revert` addresses all these issues. None of the
`grind` proofs in our test suite broke after we fixed the bugs exposed
by the new feature. That said, the traces and counterexamples produced
by `grind` are different. The new proof terms are also different.
2025-11-19 05:28:31 +00:00

100 lines
2.3 KiB
Text

module
set_option trace.grind.eqc true
set_option trace.grind.internalize true
/--
trace: [grind.internalize] [0] p
[grind.internalize] [0] q
[grind.internalize] [0] p → q
[grind.eqc] (p → q) = True
[grind.eqc] p = True
[grind.eqc] (p → q) = q
[grind.eqc] q = False
-/
#guard_msgs (trace) in
example (p q : Prop) : (p → q) → p → q := by
grind
/--
trace: [grind.internalize] [0] p
[grind.internalize] [0] q
[grind.internalize] [0] p → q
[grind.eqc] (p → q) = True
[grind.eqc] q = False
[grind.eqc] p = False
[grind.eqc] p = True
-/
#guard_msgs (trace) in
example (p q : Prop) : (p → q) → ¬q → ¬p := by
grind
/--
trace: [grind.internalize] [0] r
[grind.internalize] [0] p
[grind.internalize] [0] q
[grind.internalize] [0] (p → q) = r
[grind.internalize] [0] Prop
[grind.internalize] [0] p → q
[grind.eqc] ((p → q) = r) = True
[grind.eqc] (p → q) = r
[grind.eqc] p = False
[grind.eqc] (p → q) = True
[grind.eqc] r = False
-/
#guard_msgs (trace) in
example (p q : Prop) : (p → q) = r → ¬p → r := by
grind
/--
trace: [grind.internalize] [0] r
[grind.internalize] [0] p
[grind.internalize] [0] q
[grind.internalize] [0] (p → q) = r
[grind.internalize] [0] Prop
[grind.internalize] [0] p → q
[grind.eqc] ((p → q) = r) = True
[grind.eqc] (p → q) = r
[grind.eqc] q = True
[grind.eqc] (p → q) = True
[grind.eqc] r = False
-/
#guard_msgs (trace) in
example (p q : Prop) : (p → q) = r → q → r := by
grind
/--
trace: [grind.internalize] [0] r
[grind.internalize] [0] p
[grind.internalize] [0] q
[grind.internalize] [0] (p → q) = r
[grind.internalize] [0] Prop
[grind.internalize] [0] p → q
[grind.eqc] ((p → q) = r) = True
[grind.eqc] (p → q) = r
[grind.eqc] q = False
[grind.eqc] r = True
[grind.eqc] p = False
[grind.eqc] p = True
-/
#guard_msgs (trace) in
example (p q : Prop) : (p → q) = r → ¬q → r → ¬p := by
grind
/--
trace: [grind.internalize] [0] r
[grind.internalize] [0] p
[grind.internalize] [0] q
[grind.internalize] [0] (p → q) = r
[grind.internalize] [0] Prop
[grind.internalize] [0] p → q
[grind.eqc] ((p → q) = r) = True
[grind.eqc] (p → q) = r
[grind.eqc] q = False
[grind.eqc] r = False
[grind.eqc] p = True
[grind.eqc] p = False
-/
#guard_msgs (trace) in
example (p q : Prop) : (p → q) = r → ¬q → ¬r → p := by
grind