details about the error. They may be viewed with the `--explain` flag, or via
the [error index].
As a general rule, give an error a code (with an associated explanation) if the
explanation would give more information than the error itself. A lot of the time
it's better to put all the information in the emitted error itself. However,
sometimes that would make the error verbose or there are too many possible
triggers to include useful information for all cases in the error, in which case
it's a good idea to add an explanation.[^estebank]
As always, if you are not sure, just ask your reviewer!
If you decide to add a new error with an associated error code, please read
[this section][error-codes] for a guide and important details about the
process.
### Lints versus fixed diagnostics
Some messages are emitted via [lints](#lints), where the user can control the
level. Most diagnostics are hard-coded such that the user cannot control the
level.
Usually it is obvious whether a diagnostic should be "fixed" or a lint, but
there are some grey areas.
Here are a few examples:
- Borrow checker errors: these are fixed errors. The user cannot adjust the
level of these diagnostics to silence the borrow checker.
- Dead code: this is a lint. While the user probably doesn't want dead code in
their crate, making this a hard error would make refactoring and development
very painful.
- [future-incompatible lints]:
these are silenceable lints.
It was decided that making them fixed errors would cause too much breakage,
so warnings are instead emitted,
and will eventually be turned into fixed (hard) errors.
Hard-coded warnings (those using methods like `span_warn`) should be avoided
for normal code, preferring to use lints instead. Some cases, such as warnings
with CLI flags, will require the use of hard-coded warnings.
See the `deny` [lint level](#diagnostic-levels) below for guidelines when to
use an error-level lint instead of a fixed error.
## Diagnostic output style guide
- Write in plain simple English. If your message, when shown on a – possibly
small – screen (which hasn't been cleaned for a while), cannot be understood
by a normal programmer, who just came out of bed after a night partying,
it's too complex.
- `Error`, `Warning`, `Note`, and `Help` messages start with a lowercase
letter and do not end with punctuation.
- Error messages should be succinct. Users will see these error messages many
times, and more verbose descriptions can be viewed with the `--explain`
flag. That said, don't make it so terse that it's hard to understand.
- The word "illegal" is illegal. Prefer "invalid" or a more specific word
instead.
- Errors should document the span of code where they occur (use
[`rustc_errors::DiagCtxt`][DiagCtxt]'s
`span_*` methods or a diagnostic struct's `#[primary_span]` to easily do
this). Also `note` other spans that have contributed to the error if the span
isn't too large.
- When emitting a message with span, try to reduce the span to the smallest
amount possible that still signifies the issue
- Try not to emit multiple error messages for the same error. This may require
detecting duplicates.
- When the compiler has too little information for a specific error message,
consult with the compiler team to add new attributes for library code that
allow adding more information. For example see
[`#[rustc_on_unimplemented]`](#rustc_on_unimplemented). Use these
annotations when available!
- Keep in mind that Rust's learning curve is rather steep, and that the
compiler messages are an important learning tool.
- When talking about the compiler, call it `the compiler`, not `Rust` or
`rustc`.
- Use the [Oxford comma](https://en.wikipedia.org/wiki/Serial_comma) when
writing lists of items.
### Lint naming
From [RFC 0344], lint names should be consistent, with the following
guidelines:
The basic rule is: the lint name should make sense when read as "allow
*lint-name*" or "allow *lint-name* items". For example, "allow