- Code that is very likely to be incorrect, dangerous, or confusing, but the
language technically allows, and is not ready or confident enough to make
an error. For example `unused_comparisons` (out of bounds comparisons) or
`bindings_with_variant_name` (the user likely did not intend to create a
binding in a pattern).
- [Future-incompatible lints](#future-incompatible), where something was
accidentally or erroneously accepted in the past, but rejecting would
cause excessive breakage in the ecosystem.
- Stylistic choices. For example, camel or snake case, or the `dyn` trait
warning in the 2018 edition. These have a high bar to be added, and should
only be used in exceptional circumstances. Other stylistic choices should
either be allow-by-default lints, or part of other tools like Clippy or
rustfmt.
- `help`: emitted following an `error` or `warning` to give additional
information to the user about how to solve their problem. These messages
often include a suggestion string and [`rustc_errors::Applicability`]
confidence level to guide automated source fixes by tools. See the
[Suggestions](#suggestions) section for more details.
The error or warning portion should *not* suggest how to fix the problem,
only the "help" sub-diagnostic should.
- `note`: emitted to given more context and identify additional circumstances
and parts of the code that caused the warning or error. For example, the
borrow checker will note any previous conflicting borrows.
`help` vs `note`: `help` should be used to show changes the user can
possibly make to fix the problem. `note` should be used for everything else,
such as other context, information and facts, online resources to read, etc.
Not to be confused with *lint levels*, whose guidelines are:
- `forbid`: Lints should never default to `forbid`.
- `deny`: Equivalent to `error` diagnostic level. Some examples:
- A future-incompatible or edition-based lint that has graduated from the
warning level.
- Something that has an extremely high confidence that is incorrect, but
still want an escape hatch to allow it to pass.
- `warn`: Equivalent to the `warning` diagnostic level. See `warning` above
for guidelines.
- `allow`: Examples of the kinds of lints that should default to `allow`:
- The lint has a too high false positive rate.
- The lint is too opinionated.
- The lint is experimental.
- The lint is used for enforcing something that is not normally enforced.
For example, the `unsafe_code` lint can be used to prevent usage of unsafe
code.
More information about lint levels can be found in the [rustc
book][rustc-lint-levels] and the [reference][reference-diagnostics].
## Helpful tips and options
### Finding the source of errors
There are three main ways to find where a given error is emitted:
- `grep` for either a sub-part of the error message/label or error code. This
usually works well and is straightforward, but there are some cases where
the code emitting the error is removed from the code where the error is
constructed behind a relatively deep call-stack. Even then, it is a good way
to get your bearings.
- Invoking `rustc` with the nightly-only flag `-Z treat-err-as-bug=1`
will treat the first error being emitted as an Internal Compiler Error, which
allows you to get a
stack trace at the point the error has been emitted. Change the `1` to
something else if you wish to trigger on a later error.
There are limitations with this approach:
- Some calls get elided from the stack trace because they get inlined in the compiled `rustc`.
- The _construction_ of the error is far away from where it is _emitted_,
a problem similar to the one we faced with the `grep` approach.
In some cases, we buffer multiple errors in order to emit them in order.
- Invoking `rustc` with `-Z track-diagnostics` will print error creation
locations alongside the error.
The regular development practices apply: judicious use of `debug!()` statements