lean4-htt/tests/lean/run/variable.lean
Robert J. Simmons 3a309ba4eb
feat: improve error message in the case of type class synthesis failure (#11245)
This PR improves the error message encountered in the case of a type
class instance resolution failure, and adds an error explanation that
discusses the common new-user case of binary operation overloading and
points to the `trace.Meta.synthInstance` option for advanced debugging.

## Example

```lean4
def f (x : String) := x + x
```

Before:
```
failed to synthesize
  HAdd String String ?m.5

Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.
```

After:
```
failed to synthesize instance of type class
  HAdd String String ?m.5

Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
Error code: lean.failedToSynthesizeTypeclassInstance
[View explanation](https://lean-lang.org/doc/reference/latest/find/?domain=Manual.errorExplanation&name=lean.failedToSynthesizeTypeclassInstance)
```

The error message is changed in three important ways:
* Explains *what* failed to synthesize, using the "type class"
terminology that's more likely to be recognized than the "instance"
terminology
* Points to the `trace.Meta.synthInstance` option which is otherwise
nearly undiscoverable but is quite powerful (see also
leanprover/reference-manual#663 which is adding commentary on this
option)
* Gives an error explanation link (which won't actually work until the
next release after this is merged) which prioritizes the common-case
explanation of using the wrong binary operation
2025-11-21 21:24:27 +00:00

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

/-! # Basic section variable tests -/
/-! Directly referenced variables should be included. -/
variable {n : Nat} in
theorem t1 : n = n := by induction n <;> rfl
/-! Variables mentioned only in the body should not be included. -/
variable {n : Nat} in
/-- error: Unknown identifier `n` -/
#guard_msgs in
theorem t2 : ∃ (n : Nat), n = n := by exists n
/-! Variables transitively mentioned should be included. -/
variable {n : Nat} (h : n = n) in
theorem t3 : h = h := rfl
/-! Instance variables mentioning only included variables should be included. -/
variable {α : Type} [ToString α] in
theorem t4 (a : α) : a = a := let _ := toString a; rfl
/-! Instance variables not mentioning only included variables should not be included. -/
variable {α β : Type} [Coe α β] in
/--
error: don't know how to synthesize placeholder
context:
α : Type
a : α
⊢ a = a
-/
#guard_msgs in
theorem t5 (a : α) : a = a := _
/-! Accidentally included variables should be warned for. -/
variable {α : Type} [ToString α] in
/--
warning: automatically included section variable(s) unused in theorem `t6`:
[ToString α]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [ToString α] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
-/
#guard_msgs in
theorem t6 (a : α) : a = a := rfl
/-! `include` should always include. -/
variable {n : Nat} in
include n in
theorem t7 : ∃ (n : Nat), n = n := by exists n
/-! traversal order bug broke instance inclusion -/
variable {M N : Type} (r : N → N → Prop)
class IsTrans (N : Type) (r : N → N → Prop) : Prop
variable [IsTrans N r] {a b c d : N}
/--
warning: automatically included section variable(s) unused in theorem `act_rel_of_rel_of_act_rel`:
[IsTrans N r]
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit [IsTrans N r] in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
-/
#guard_msgs in
theorem act_rel_of_rel_of_act_rel (ab : r a b) : r a b := ab
/-! More complex include case, instance should be included via `f`. -/
class EquivLike (F : Type) (α β : Type) : Type
variable {F : Type} [EquivLike F α β] (f : F) in
include f in
theorem MulEquiv.decompositionMonoid (_b : β) : α = α :=
let _ : EquivLike F α β := inferInstance; let _ := f; rfl
/-- info: MulEquiv.decompositionMonoid {α β F : Type} [EquivLike F α β] (f : F) (_b : β) : α = α -/
#guard_msgs in
#check MulEquiv.decompositionMonoid
section
/-! `omit` -/
variable [ToString α] [ToString β]
/--
error: failed to synthesize instance of type class
ToString α
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/
#guard_msgs in
omit [ToString α] in
theorem t8 (a : α) (b : β) : True :=
let _ := toString a; let _ := toString b; trivial
/--
error: failed to synthesize instance of type class
ToString β
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/
#guard_msgs in
omit [ToString β] in
theorem t9 (a : α) (b : β) : True :=
let _ := toString a; let _ := toString b; trivial
/--
error: failed to synthesize instance of type class
ToString α
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
---
error: failed to synthesize instance of type class
ToString β
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/
#guard_msgs in
omit [ToString _] in
theorem t10 (a : α) (b : β) : True :=
let _ := toString a; let _ := toString b; trivial
end
/-! illegal `omit`s -/
/-- error: invalid 'omit', `α` has not been declared in the current scope -/
#guard_msgs in
variable (a : α) in
omit α in
theorem t11 (a : α) : True := trivial
/-- error: cannot omit referenced section variable `α` -/
#guard_msgs in
variable (α : Type) in
omit α in
theorem t12 (a : α) : True := trivial
/-- error: cannot omit referenced section variable `inst✝` -/
#guard_msgs in
variable [ToString α] in
omit [ToString α] in
theorem t13 (a : α) : toString a = toString a := rfl
set_option pp.mvars false in
/--
error: Application type mismatch: The argument
True
has type
Prop
of sort `Type` but is expected to have type
Type _
of sort `Type (_ + 1)` in the application
ToString True
-/
#guard_msgs in
omit [ToString True]
/-- error: `[ToString Nat]` did not match any variables in the current scope -/
#guard_msgs in
omit [ToString Nat]
/-! `omit` can also be used to revert an `include` -/
variable (α : Type) in
include α in
omit α in
theorem t14 : True := trivial
/--
warning: automatically included section variable(s) unused in theorem `t15`:
α
consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them:
omit α in theorem ...
Note: This linter can be disabled with `set_option linter.unusedSectionVars false`
-/
#guard_msgs in
variable (α : Type) in
include α in
omit α in
include α in
theorem t15 : True := trivial
/-! But you probably shouldn't use it -/
set_option linter.omit true in
/--
warning: `omit` should be avoided in favor of restructuring your `variable` declarations
Note: This linter can be disabled with `set_option linter.omit false`
-/
#guard_msgs in
variable (α : Type) in
include α in
omit α in
theorem t16 : True := trivial