lean4-htt/tests/lean/run/prelude-injectivity.lean
Kim Morrison 226a90f1eb
feat: exact? +grind and exact? +try? discharger options (#11469)
This PR adds `+grind` and `+try?` options to `exact?` and `apply?`
tactics.

## `+grind` option

When `+grind` is enabled, `grind` is used as a fallback discharger for
subgoals that `solve_by_elim` cannot close. The proof is wrapped in
`Grind.Marker` so suggestions display `(by grind)` instead of the
complex grind proof term.

Example:
```lean
axiom foo (x : Nat) : x < 37 → 5 < x → x.log2 < 6

/--
info: Try this:
  [apply] exact foo x (by grind) (by grind)
-/
#guard_msgs in
example (x : Nat) (h₁ : x < 30) (h₂ : 8 < x) : x.log2 < 6 := by
  exact? +grind
```

## `+try?` option

When `+try?` is enabled, `try?` is used as a fallback discharger for
subgoals. This is useful when subgoals require induction or other
strategies that `try?` can find but `solve_by_elim` and `grind` cannot.

Example:
```lean
inductive MyList (α : Type _) where
  | nil : MyList α
  | cons : α → MyList α → MyList α

axiom MyListProp : MyList α → Prop
@[grind .] axiom mylist_nil : MyListProp (MyList.nil : MyList α)
@[grind .] axiom mylist_cons : ∀ (x : α) (xs : MyList α), MyListProp xs → MyListProp (MyList.cons x xs)

axiom qux (xs : MyList α) (p : MyListProp xs) : MyListProp2 xs

/--
info: Try this:
  [apply] exact qux xs (by try?)
-/
example (xs : MyList α) : MyListProp2 xs := by
  exact? +try?
```

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 06:31:56 +00:00

51 lines
1.6 KiB
Text

module
import Lean
open Lean Meta
-- without this, the catch below does not catch kernel errors
set_option Elab.async false
/--
info: Possible candidates for Init/Core.lean (these do not need to be added if they are irrelevant for verification):
gen_injective_theorems% MacroScopesView
gen_injective_theorems% ParserDescr
gen_injective_theorems% SourceInfo
gen_injective_theorems% TSyntax
gen_injective_theorems% Macro.Context
gen_injective_theorems% Macro.Exception
gen_injective_theorems% Macro.Methods
gen_injective_theorems% Syntax.Preresolved
gen_injective_theorems% Syntax.SepArray
gen_injective_theorems% Syntax.TSepArray
gen_injective_theorems% Try.Config
gen_injective_theorems% Parser.Tactic.DecideConfig
gen_injective_theorems% Parser.Tactic.LibrarySearchConfig
-/
#guard_msgs in
run_meta
let mut names := #[]
for (name, ci) in (← getEnv).constants do
let .inductInfo info := ci | continue
if info.isUnsafe then continue
if isClass (← getEnv) name then continue
let bad ← do
try
let env0 ← getEnv
mkInjectiveTheorems name
let env1 ← getEnv
if env1.constants.map₂.toArray.size > env0.constants.map₂.toArray.size then
pure true
else
pure false
catch _ =>
pure false
if bad then
names := names.push name
unless names.isEmpty do
names := names.qsort Name.lt
let mut msg := m!"Possible candidates for Init/Core.lean (these do not need to be added if they are irrelevant for verification):\n"
for n in names do
msg := msg ++ m!"gen_injective_theorems% {.ofConstName n}\n"
logInfo msg