lean4-htt/tests/elab/5407.lean
Garmelon 08eb78a5b2
chore: switch to new test/bench suite (#12590)
This PR sets up the new integrated test/bench suite. It then migrates
all benchmarks and some related tests to the new suite. There's also
some documentation and some linting.

For now, a lot of the old tests are left alone so this PR doesn't become
even larger than it already is. Eventually, all tests should be migrated
to the new suite though so there isn't a confusing mix of two systems.
2026-02-25 13:51:53 +00:00

202 lines
5 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.

/-!
# Suggestion tactics should not return invalid tactics
https://github.com/leanprover/lean4/issues/5407
The "suggestion" tactics `exact?`, `apply?`, `show_term`, and `rw?` should not suggest proof terms
that do not compile. They should use `expose_names` where possible to render suggestions valid. If
an invalid proof is generated, these tactics should instead provide users with appropriate feedback.
-/
/-! Discards unprintable implicit argument to lambda -/
inductive Odd : Nat → Prop
| one : Odd 1
| add_two : Odd n → Odd (n + 2)
theorem odd_iff {n : Nat} : Odd n ↔ n % 2 = 1 := by
refine ⟨fun h => by induction h <;> omega, ?_⟩
match n with
| 0 => simp
| 1 => exact fun _ => Odd.one
| n + 2 => exact fun _ => Odd.add_two (odd_iff.mpr (by omega))
/--
error: found a proof, but the corresponding tactic failed:
(expose_names; exact fun a => (fun {n} => odd_iff.mpr) a)
It may be possible to correct this proof by adding type annotations, explicitly specifying implicit arguments, or eliminating unnecessary function abstractions.
-/
#guard_msgs in
example {n : Nat} : n % 2 = 1 → Odd n :=
by exact?
/-! Detects shadowed variables -/
opaque A : Type
opaque B : Type
opaque C : Prop
axiom imp : A → B → C
axiom a : A
axiom b : B
/--
info: Try this:
[apply] (expose_names; exact imp h_1 h)
-/
#guard_msgs in
example : C := by
have h : A := a
have h : B := b
exact?
/-! Detects lambdas with insufficient explicit binder types -/
inductive EqExplicit {α} : αα → Prop
| intro : (a b : α) → a = b → EqExplicit a b
/--
error: found a proof, but the corresponding tactic failed:
(expose_names; exact EqExplicit.intro (fun f => (fun g x => g x) f) id rfl)
It may be possible to correct this proof by adding type annotations, explicitly specifying implicit arguments, or eliminating unnecessary function abstractions.
-/
#guard_msgs in
example : EqExplicit (fun (f : α → β) => (fun g x => g x) f) id := by
exact?
/-! `exact?` no longer uses `solve_by_elim` first, so it can't find local hypotheses.
However, star-indexed lemmas (like `Function.comp`) may find a proof via fallback. -/
#guard_msgs (drop info) in
example {P : Prop} : P → P := by
intro
exact?
/-! Does *not* suggest `expose_names` when the inaccessible name is an implicit argument. -/
opaque D : Nat → Type
axiom c_of_d {n : Nat} : D n → C
/--
info: Try this:
[apply] exact c_of_d x
-/
#guard_msgs in
example : (n : Nat) → D n → C := by
intro
intro x
exact?
/-! `apply?` logs info instead of erroring -/
opaque E : Prop
axiom option1 : A → E
axiom option2 {_ : B} : E
/--
info: Try this:
[apply] refine option1 ?_
-- Remaining subgoals:
-- ⊢ A
---
info: found a partial proof, but the corresponding tactic failed:
(expose_names; refine option2)
It may be possible to correct this proof by adding type annotations, explicitly specifying implicit arguments, or eliminating unnecessary function abstractions.
---
warning: declaration uses `sorry`
-/
#guard_msgs in
example : E := by apply?
/-!
This `apply?` erroneously reports a failure if suggesting tactics with dot-focusing notation instead
of parenthesized sequencing.
-/
opaque R : A → B → Prop
axiom rImp (b : B) : R a b → R a b
/--
info: Try this:
[apply] (expose_names; refine rImp b ?_)
-- Remaining subgoals:
-- ⊢ R a b
---
warning: declaration uses `sorry`
-/
#guard_msgs in
example : (b : B) → R a b := by
intro
apply?
/-! `show_term` exhibits the same behavior as `exact?` -/
/--
info: Try this:
[apply] (expose_names; exact h)
-/
#guard_msgs in
example : E → E := by
intro
show_term assumption
/--
info: found a partial proof, but the corresponding tactic failed:
(expose_names; refine option2)
It may be possible to correct this proof by adding type annotations, explicitly specifying implicit arguments, or eliminating unnecessary function abstractions.
---
error: unsolved goals
a✝ : B
⊢ B
-/
#guard_msgs in
example : B → E := by
intro
show_term apply option2
/--
info: Try this:
[apply] exact c_of_d d
-/
#guard_msgs in
example : (n : Nat) → D n → C := by
intro _ d
show_term apply c_of_d d
/-! `rw?` exhibits the same behavior as above. -/
namespace Rw
opaque A : Type
@[instance] axiom inst : Inhabited A
opaque Foo (a a' : A) : Prop
noncomputable opaque a : A
axiom eq (a' : A) : a = a'
/--
info: Try this:
[apply] (expose_names; rw [eq a'])
-- Foo a' a'
---
error: unsolved goals
a'✝ : A
⊢ Foo a'✝ a'✝
-/
#guard_msgs in
example : (a' : A) → Foo a a' := by
intro
rw?
noncomputable opaque a₁ : A
axiom eq_imp {a' : A} : a₁ = a'
/--
info: found an applicable rewrite lemma, but the corresponding tactic failed:
(expose_names; rw [eq_imp])
-- Foo a' a'
It may be possible to correct this proof by adding type annotations, explicitly specifying implicit arguments, or eliminating unnecessary function abstractions.
---
error: unsolved goals
a'✝ : A
⊢ Foo a'✝ a'✝
-/
#guard_msgs in
example : (a' : A) → Foo a₁ a' := by
intro
rw?