lean4-htt/tests/lean/run/5407.lean
Marc Huisinga f180eee7bf
feat: use widget message for "try this" (#9966)
This PR adjusts the "try this" widget to be rendered as a widget message
under 'Messages', not a separate widget under a 'Suggestions' section.
The main benefit of this is that the message of the widget is not
duplicated between 'Messages' and 'Suggestions'.

Since widget message suggestions were already implemented by @jrr6 for
the new hint infrastructure, this PR replaces the old "try this"
implementation with the new hint infrastructure. In doing so, the
`style?` field of suggestions is deprecated, since the hint
infrastructure highlights hints using diff colors, and `style?` also
never saw much use downstream. Additionally, since the message and the
suggestion are now the same component, the `messageData?` field of
suggestions is deprecated as well. Notably, the "Try this:" message
string now also contains a newline and indentation to separate the
suggestion from the rest of the message more clearly and the `postInfo?`
field of the suggestion is now part of the message.

Finally, this PR changes the diff colors used by the hint infrastructure
to be more color-blindness-friendly (insertions are now blue, not green,
and text that remains unchanged is now using the editor foreground color
instead of blue).

### Breaking changes
Tests that use `#guard_msgs` to test the "Try this:" message may need to
be adjusted for the new formatting of the message.
2025-08-26 12:15:32 +00:00

205 lines
4.8 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:
(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?
/-! Suggests `expose_names` if a name in the syntax contains macro scopes -/
/--
info: Try this:
(expose_names; exact h)
-/
#guard_msgs 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:
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:
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:
(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:
(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:
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:
(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?