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
52 lines
1.5 KiB
Text
52 lines
1.5 KiB
Text
class Foo (s : String) : Type where
|
|
instance : Foo "one" where
|
|
instance [Foo "three"] : Foo "two" where
|
|
|
|
def f (s : String) [Foo s] := ()
|
|
|
|
/-- info: () -/
|
|
#guard_msgs in
|
|
#eval f "one"
|
|
|
|
/--
|
|
error: failed to synthesize instance of type class
|
|
Foo "two"
|
|
|
|
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
|
|
-/
|
|
#guard_msgs in
|
|
#eval f "two"
|
|
|
|
/--
|
|
error: failed to synthesize instance of type class
|
|
Foo "two"
|
|
---
|
|
trace: [Meta.synthInstance] ❌️ Foo "two"
|
|
[Meta.synthInstance] new goal Foo "two"
|
|
[Meta.synthInstance.instances] #[@instFoo_1]
|
|
[Meta.synthInstance] ✅️ apply @instFoo_1 to Foo "two"
|
|
[Meta.synthInstance.tryResolve] ✅️ Foo "two" ≟ Foo "two"
|
|
[Meta.synthInstance] no instances for Foo "three"
|
|
[Meta.synthInstance.instances] #[]
|
|
[Meta.synthInstance] result <not-available>
|
|
[Meta.synthInstance] ❌️ Foo "two"
|
|
[Meta.synthInstance] result <not-available> (cached)
|
|
-/
|
|
#guard_msgs in
|
|
set_option trace.Meta.synthInstance true in
|
|
#eval f "two"
|
|
|
|
/--
|
|
error: failed to synthesize instance of type class
|
|
Foo "three"
|
|
---
|
|
trace: [Meta.synthInstance] ❌️ Foo "three"
|
|
[Meta.synthInstance] no instances for Foo "three"
|
|
[Meta.synthInstance.instances] #[]
|
|
[Meta.synthInstance] result <not-available>
|
|
[Meta.synthInstance] ❌️ Foo "three"
|
|
[Meta.synthInstance] result <not-available> (cached)
|
|
-/
|
|
#guard_msgs in
|
|
set_option trace.Meta.synthInstance true in
|
|
#eval f "three"
|