lean4-htt/tests/lean/run/grind_pattern_inference_issue.lean
Leonardo de Moura 6b387da032
feat: new E-matching pattern inference for grind (#10342)
This PR implements a new E-matching pattern inference procedure that is
faithful to the behavior documented in the reference manual regarding
minimal indexable subexpressions. The old inference procedure was
failing to enforce this condition. For example, the manual documents
`[grind ->]` as follows

`[@grind →]` selects a multi-pattern from the hypotheses of the theorem.
In other words, `grind` will use the theorem for forwards reasoning.

To generate a pattern, it traverses the hypotheses of the theorem from
left to right. Each time it encounters a **minimal indexable
subexpression** which covers an argument which was not previously
covered, it adds that subexpression as a pattern, until all arguments
have been covered.

That said, the new procedure is currently disabled, and the following
option must be used to enable it.
```
set_option backward.grind.inferPattern false
```
Users can inspect differences between the old a new procedures using the
option
```
set_option backward.grind.checkInferPatternDiscrepancy true 
```
Example:
```lean
/--
warning: found discrepancy between old and new `grind` pattern inference procedures, old:
  [@List.length #2 (@toList _ #1 #0)]
new:
  [@toList #2 #1 #0]
use `set_option backward.grind.inferPattern true` to force old procedure
-/
#guard_msgs in
set_option backward.grind.checkInferPatternDiscrepancy true in
@[grind] theorem Vector.length_toList' (xs : Vector α n) : xs.toList.length = n := by sorry
```
2025-09-11 05:27:11 +00:00

35 lines
1.3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

set_option warn.sorry false
namespace Test
set_option backward.grind.inferPattern false -- Force new pattern inference procedure
inductive Vector (α : Type) : Nat → Type where
| nil : Vector α 0
| cons (x : α) (xs : Vector α n) : Vector α (n + 1)
def Vector.ofList (xs : List α) (h : xs.length = n) : Vector α n :=
match n, xs with
| 0, [] => .nil
| (n + 1), x :: xs => .cons x (.ofList xs (by grind))
def Vector.toList (xs : Vector α n) : List α :=
match xs with
| .nil => []
| .cons x xs => x :: xs.toList
/-- info: length_toList: [@toList #2 #1 #0] -/
#guard_msgs (info) in
@[grind?] theorem Vector.length_toList (xs : Vector α n) : xs.toList.length = n := by sorry
def wrapper (f : Nat → Nat → List α → List α) (h : ∀ n m xs, xs.length = n → (f n m xs).length = m) :
(n m : Nat) → Vector α n → Vector α m :=
fun n m xs => Vector.ofList (f n m xs.toList) (by grind) -- apply h; apply Vector.length_toList) -- fails here: (by grind)
/--
warning: found discrepancy between old and new `grind` pattern inference procedures, old:
[@List.length #2 (@toList _ #1 #0)]
new:
[@toList #2 #1 #0]
-/
#guard_msgs in
set_option backward.grind.checkInferPatternDiscrepancy true in
@[grind] theorem Vector.length_toList' (xs : Vector α n) : xs.toList.length = n := by sorry