Skip to content

Commit 3a309ba

Browse files
authored
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
1 parent 4288aa7 commit 3a309ba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+291
-142
lines changed

src/Lean/Elab/Term/TermElabM.lean

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,16 @@ def containsPendingMVar (e : Expr) : MetaM Bool := do
11131113
| some _ => return false
11141114
| none => return true
11151115

1116+
/--
1117+
If the `trace.Meta.synthInstance` option is not already set, gives a hint explaining this option.
1118+
-/
1119+
def useTraceSynthMsg : MessageData :=
1120+
MessageData.lazy fun ctx =>
1121+
if trace.Meta.synthInstance.get ctx.opts then
1122+
pure ""
1123+
else
1124+
pure <| .hint' s!"Type class instance resolution failures can be inspected with the `set_option {trace.Meta.synthInstance.name} true` command."
1125+
11161126
/--
11171127
Try to synthesize metavariable using type class resolution.
11181128
This method assumes the local context and local instances of `instMVar` coincide
@@ -1171,7 +1181,7 @@ def synthesizeInstMVarCore (instMVar : MVarId) (maxResultSize? : Option Nat := n
11711181
if (← read).ignoreTCFailures then
11721182
return false
11731183
else
1174-
throwError "failed to synthesize{indentExpr type}{extraErrorMsg}{useDiagnosticMsg}"
1184+
throwNamedError lean.synthInstanceFailed "failed to synthesize instance of type class{indentExpr type}{extraErrorMsg}{useTraceSynthMsg}"
11751185

11761186
def mkCoe (expectedType : Expr) (e : Expr) (f? : Option Expr := none) (errorMsgHeader? : Option String := none)
11771187
(mkErrorMsg? : Option (MVarId → (expectedType e : Expr) → MetaM MessageData) := none)

src/Lean/ErrorExplanations.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ public import Lean.ErrorExplanations.InvalidDottedIdent
1616
public import Lean.ErrorExplanations.ProjNonPropFromProp
1717
public import Lean.ErrorExplanations.PropRecLargeElim
1818
public import Lean.ErrorExplanations.RedundantMatchAlt
19+
public import Lean.ErrorExplanations.SynthInstanceFailed
1920
public import Lean.ErrorExplanations.UnknownIdentifier

src/Lean/ErrorExplanations/CtorResultingTypeMismatch.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ constructor if the inductive type being defined has no indices.
2020
2121
# Examples
2222
23-
## Typo in resulting type
23+
## Typo in Resulting Type
2424
```lean broken
2525
inductive Tree (α : Type) where
2626
| leaf : Tree α
@@ -38,7 +38,7 @@ inductive Tree (α : Type) where
3838
| node : α → Tree α → Tree α
3939
```
4040
41-
## Missing resulting type after constructor parameter
41+
## Missing Resulting Type After Constructor Parameter
4242
4343
```lean broken
4444
inductive Credential where

src/Lean/ErrorExplanations/DependsOnNoncomputable.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ definitions.
2626
2727
# Examples
2828
29-
## Necessarily noncomputable function not appropriately marked
29+
## Necessarily Noncomputable Function Not Appropriately Marked
3030
3131
```lean broken
3232
axiom transform : Nat → Nat
@@ -50,7 +50,7 @@ axiom, it does not contain any executable code; although the value `transform 0`
5050
there is no way to compute its value. Thus, `transformIfZero` must be marked `noncomputable` because
5151
its execution would depend on this axiom.
5252
53-
## Noncomputable dependency can be made computable
53+
## Noncomputable Dependency Can Be Made Computable
5454
5555
```lean broken
5656
noncomputable def getOrDefault [Nonempty α] : Option α → α
@@ -81,7 +81,7 @@ version of `getOrDefault` (using the `Inhabited` type class), allowing `endsOrDe
8181
computable. (The differences between `Inhabited` and `Nonempty` are described in the documentation
8282
of inhabited types in the manual section on [Basic Classes](lean-manual://section/basic-classes).)
8383
84-
## Noncomputable instance in namespace
84+
## Noncomputable Instance in Namespace
8585
8686
```lean broken
8787
open Classical in

src/Lean/ErrorExplanations/InductiveParamMismatch.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ parameters to indices.
2626
2727
# Examples
2828
29-
## Vector length index as a parameter
29+
## Vector Length Index as a Parameter
3030
3131
```lean broken
3232
inductive Vec (α : Type) (n : Nat) : Type where

src/Lean/ErrorExplanations/InductiveParamMissing.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ between indices and parameters.
2424
2525
# Examples
2626
27-
## Omitting parameter in argument to higher-order predicate
27+
## Omitting Parameter in Argument to Higher-Order Predicate
2828
2929
```lean broken
3030
inductive List.All {α : Type u} (P : α → Prop) : List α → Prop

src/Lean/ErrorExplanations/InferBinderTypeFailed.lean

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ The first three cases are demonstrated in examples below.
4343
4444
# Examples
4545
46-
## Binder type requires new type variable
46+
## Binder Type Requires New Type Variable
4747
4848
```lean broken
4949
def identity x :=
@@ -63,7 +63,7 @@ specified explicitly. Note that if automatic implicit parameter insertion is ena
6363
default), a binder for `α` itself need not be provided; Lean will insert an implicit binder for this
6464
parameter automatically.
6565
66-
## Uninferred binder type due to resulting type annotation
66+
## Uninferred Binder Type Due to Resulting Type Annotation
6767
6868
```lean broken
6969
def plusTwo x : Nat :=
@@ -86,7 +86,7 @@ determined, resulting in the shown error. It is therefore necessary to include t
8686
its binder.
8787
8888
89-
## Attempting to name an example declaration
89+
## Attempting to Name an Example Declaration
9090
9191
```lean broken
9292
example trivial_proof : True :=
@@ -106,7 +106,7 @@ be named, and an identifier written where a name would appear in other declarati
106106
elaborated as a binder, whose type cannot be inferred. If a declaration must be named, it should be
107107
defined using a declaration form that supports naming, such as `def` or `theorem`.
108108
109-
## Attempting to define multiple opaque constants at once
109+
## Attempting to Define Multiple Opaque Constants at Once
110110
111111
```lean broken
112112
opaque m n : Nat
@@ -128,7 +128,7 @@ instead elaborated as defining a single constant (e.g., `m` above) with paramete
128128
subsequent identifiers (`n`), whose types are unspecified and cannot be inferred. To define multiple
129129
global constants, it is necessary to declare each separately.
130130
131-
## Attempting to define multiple structure fields on the same line
131+
## Attempting to Define Multiple Structure Fields on the Same Line
132132
133133
```lean broken
134134
structure Person where

src/Lean/ErrorExplanations/InferDefTypeFailed.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ will never attempt to use the theorem body to infer the proposition being proved
3535
3636
# Examples
3737
38-
## Implicit argument cannot be inferred
38+
## Implicit Argument Cannot be Inferred
3939
4040
```lean broken
4141
def emptyNats :=
@@ -60,7 +60,7 @@ the expected type of the definition allows Lean to infer the appropriate implici
6060
`List.nil` constructor; alternatively, making this implicit argument explicit in the function body
6161
provides sufficient information for Lean to infer the definition's type.
6262
63-
## Definition type uninferrable due to unknown parameter type
63+
## Definition Type Uninferrable Due to Unknown Parameter Type
6464
6565
```lean broken
6666
def identity x :=

src/Lean/ErrorExplanations/InvalidDottedIdent.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ universe (e.g., `Prop` or `Type`), as dotted-identifier notation is not supporte
2323
2424
# Examples
2525
26-
## Insufficient type information
26+
## Insufficient Type Information
2727
2828
```lean broken
2929
def reverseDuplicate (xs : List α) :=
@@ -46,7 +46,7 @@ resolves: if the return type is `T`, then Lean will (attempt to) resolve `.reve
4646
`T.reverse` whose return type is `T`—even if `T.reverse` does not take an argument of type
4747
`List α`.
4848
49-
## Dotted identifier where type universe expected
49+
## Dotted Identifier Where Type Universe Expected
5050
5151
```lean broken
5252
example (n : Nat) :=

src/Lean/ErrorExplanations/ProjNonPropFromProp.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ such elimination is only valid if the resulting value is also in `Prop`; if it i
2525
2626
# Examples
2727
28-
## Attempting to use index projection on existential proof
28+
## Attempting to Use Index Projection on Existential Proof
2929
3030
```lean broken
3131
example (a : Nat) (h : ∃ x : Nat, x > a + 1) : ∃ x : Nat, x > 0 :=

0 commit comments

Comments
 (0)