Skip to content

Commit

Permalink
Document the advanced error formatting engine
Browse files Browse the repository at this point in the history
  • Loading branch information
tek committed Apr 7, 2021
1 parent 0aa3fde commit b205b34
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 1 deletion.
15 changes: 14 additions & 1 deletion _data/compiler-options.yml
Expand Up @@ -611,9 +611,22 @@
- option: "-Vimplicits"
schema:
type: "Boolean"
description: "Show more detail on why some implicits are not applicable."
description: "Print dependent missing implicits."
abbreviations:
- "-Xlog-implicits"
- option: "-Vimplicits-verbose-tree"
schema:
type: "Boolean"
description: "Display all intermediate implicits in a chain."
- option: "-Vimplicits-max-refined"
schema:
type: "Int"
default: "0"
description: "max chars for printing refined types, abbreviate to `F {...}`"
- option: "-Vtype-diffs"
schema:
type: "Boolean"
description: "Print found/required error messages as colored diffs."
- option: "-Vinline"
schema:
type: "String"
Expand Down
5 changes: 5 additions & 0 deletions _data/overviews.yml
Expand Up @@ -254,6 +254,11 @@
icon: cog
url: "compiler-options/index.html"
description: "Various options to control how scalac compiles your code."
- title: Error Formatting
by: Torsten Schmits
icon: cog
url: "compiler-options/errors.html"
description: "A new engine for more user-friendly error messages, printing chains of dependent implicits and colored found/required type diffs."


- category: Legacy
Expand Down
105 changes: 105 additions & 0 deletions _overviews/compiler-options/errors.md
@@ -0,0 +1,105 @@
# Introduction

An advanced mechanism for formatting type errors and inspecting missing
implicits has been introduced in Scala 2.13.6.
It is based on the compiler plugin [splain](https://github.com/tek/splain).

This tool abstracts several classes of compiler errors with simple data types
that can be processed by a few built-in routines as well as
[user-provided analyzer plugins](/overviews/plugins/index.html).

The most significant feature is the illustration of chains of implicit instances
that allows a user to determine the root cause of an implicit error:

![implicits](/resources/img/implicits-circe.jpg)

# Basic Configuration

* `-Vimplicits` enables printing of implicit chains
* `-Vtype-diffs` enables colored diffs for found/required errors

## Additional Configuration

`-Vimplicits-verbose-tree` shows the implicits between the error site and the
root cause, see [#implicit-resolution-chains].

`-Vimplicits-max-refined` reduces the verbosity of refined types, see
[#truncating-refined-types].

# Features

The error formatting engine provides the following enhancements:

## Infix Types

Instead of `shapeless.::[A, HNil]`, prints `A :: HNil`.

## Found/Required Types

Rather than printing up to four types, only the dealiased types are shown as a colored diff:

![foundreq](/resources/img/foundreq.jpg)

## Implicit Resolution Chains

When an implicit is not found, only the outermost error at the invocation point is printed by the regular error
reporter.
Previously, the flag `-Xlog-implicits` caused the compiler to print all information about processed implicits, but the
output was highly verbose and contained all invalid implicits for parameters that have been resolved successfully.
The flag has been renamed to `-Vimplicits` and prints a compact list of all involved implicit instances.
`-Xlog-implicits` will continue to work as a deprecated alias.

![compact](/resources/img/implicits-compact.jpg)

Here, `!I` stands for *could not find implicit value*, the name of the implicit
parameter is in yellow, and its type in green.

If the parameter `-Vimplicits-verbose-tree` is given, all intermediate implicits will be
printed, potentially spanning tens of lines.
An example of this is the circe error at the top of the page.

For comparison, this is the regular compiler output for this case:

```
[error] /path/Example.scala:20:5: could not find implicit value for parameter a: io.circe.Decoder[A]
[error] A.fun
[error] ^
```

## Infix Type and Type Argument Line Breaking

Types longer than 79 characters will be split into multiple lines:

```
implicit error;
!I e: String
f invalid because
!I impPar4: List[
(
VeryLongTypeName ::::
VeryLongTypeName ::::
VeryLongTypeName ::::
VeryLongTypeName
)
::::
(Short :::: Short) ::::
(
VeryLongTypeName ::::
VeryLongTypeName ::::
VeryLongTypeName ::::
VeryLongTypeName
)
::::
VeryLongTypeName ::::
VeryLongTypeName ::::
VeryLongTypeName ::::
VeryLongTypeName
]
```

## Truncating Refined Types

Refined types, like `T { type A = X; type B = Y }`, can get rather long and clutter up error messages.
The option `-Vimplicits-max-refined` controls how many characters the refinement may take up before it gets displayed as
`T {...}`.
The default is to display the unabridged type.
Binary file added resources/img/foundreq.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/foundreq_record.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/implicits-circe.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/img/implicits-compact.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b205b34

Please sign in to comment.