lean4-htt/tests/lean/run/grind_pattern_inference_issue.lean
Leonardo de Moura efb398b040
feat: new grind pattern inference heuristic and code action (#10422)
This PR implements the new E-matching pattern inference heuristic for
`grind`. It is not enabled yet. You can activate the new behavior using
`set_option backward.grind.inferPattern false`. Here is a summary of the
new behavior.

* `[grind =]`, `[grind =_]`, `[grind _=_]`, `[grind <-=]`: no changes;
we keep the current behavior.
  
* `[grind ->]`, `[grind <-]`, `[grind =>]`, `[grind <=]`: we stop using
the *minimal indexable subexpression* and instead use the first
indexable one.

* `[grind! <mod>]`: behaves like `[grind <mod>]` but uses the minimal
indexable subexpression restriction. We generate an error if the user
writes `[grind! =]`, `[grind! =_]`, `[grind! _=_]`, or `[grind! <-=]`,
since there is no pattern search in these cases.
  
* `[grind]`: it tries `=`, `=_`, `<-`, `->`, `<=`, `=>` with and without
the minimal indexable subexpression restriction. For the ones that work,
we generate a code action to encourage users to select the one they
prefer.

* `[grind!]`: it tries `<-`, `->`, `<=`, `=>` using the minimal
indexable subexpression restriction. For the ones that work, we generate
a code action to encourage users to select the one they prefer.

* `[grind? <mod>]`: where `<mod>` is one of the modifiers above, it
behaves like `[grind <mod>]` but also displays the pattern.
  
Example:
```lean
/--
info: Try these:
  • [grind =] for pattern: [f (g #0)]
  • [grind =_] for pattern: [r #0 #0]
  • [grind! ←] for pattern: [g #0]
-/
#guard_msgs in
@[grind] axiom fg₇ : f (g x) = r x x
```
2025-09-17 02:44: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