Skip to content

Commit 39edbe5

Browse files
ehussmark-i-m
authored andcommitted
Add some guidelines on diagnostics.
1 parent aca2a71 commit 39edbe5

File tree

1 file changed

+159
-1
lines changed

1 file changed

+159
-1
lines changed

src/diagnostics.md

+159-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
A lot of effort has been put into making `rustc` have great error messages.
44
This chapter is about how to emit compile errors and lints from the compiler.
55

6-
## Diagnostic output style guide
6+
## Diagnostic structure
77

88
The main parts of a diagnostic error are the following:
99

@@ -61,6 +61,163 @@ error: the fobrulator needs to be krontrificated
6161
When code or an identifier must appear in an message or label, it should be
6262
surrounded with single acute accents \`.
6363

64+
### Error explanations
65+
66+
Some errors include long form descriptions. They may be viewed with the
67+
`--explain` flag, or via the [error index]. Each explanation comes with an
68+
example of how to trigger it and advice on how to fix it.
69+
70+
Please read [RFC 1567] for details on how to format and write long error
71+
codes.
72+
73+
The descriptions are written in markdown, and all of them are linked in the
74+
[`librustc_error_codes`] crate.
75+
76+
<!-- TODO: When should an error use an error code, and when shouldn't it? -->
77+
78+
[`librustc_error_codes`]: https://github.com/rust-lang/rust/blob/master/src/librustc_error_codes/error_codes.rs
79+
[error index]: https://doc.rust-lang.org/error-index.html
80+
[RFC 1567]: https://github.com/rust-lang/rfcs/blob/master/text/1567-long-error-codes-explanation-normalization.md
81+
82+
### Lints versus fixed diagnostics
83+
84+
Some messages are emitted via [lints](#lints), where the user can control the
85+
level. Some are hard-coded such that the user cannot control the level.
86+
87+
Hard-coded warnings should be avoided for normal code, preferring to use lints
88+
instead. Some cases, such as warnings with CLI flags will require the use of
89+
hard-coded warnings.
90+
91+
See the `deny` [lint level](#diagnostic-levels) below for guidelines when to
92+
use an error-level lint instead of a fixed error.
93+
94+
## Diagnostic output style guide
95+
96+
- Write in plain simple English. If your message, when shown on a – possibly
97+
small – screen (which hasn't been cleaned for a while), cannot be understood
98+
by a normal programmer, who just came out of bed after a night partying,
99+
it's too complex.
100+
- `Error`, `Warning`, `Note`, and `Help` messages start with a lowercase
101+
letter and do not end with punctuation.
102+
- Error messages should be succinct. Users will see these error messages many
103+
times, and more verbose descriptions can be viewed with the `--explain`
104+
flag. That said, don't make it so terse that it's hard to understand.
105+
- The word "illegal" is illegal. Prefer "invalid" or a more specific word
106+
instead.
107+
- Errors should document the span of code where they occur – the `span_..`
108+
methods allow to easily do this. Also `note` other spans that have
109+
contributed to the error if the span isn't too large.
110+
- When emitting a message with span, try to reduce the span to the smallest
111+
amount possible that still signifies the issue
112+
- Try not to emit multiple error messages for the same error. This may require
113+
detecting duplicates.
114+
- When the compiler has too little information for a specific error message,
115+
lobby for annotations for library code that allow adding more. For example
116+
see [`#[rustc_on_unimplemented]`](#rustc_on_unimplemented). Use these
117+
annotations when available!
118+
- Keep in mind that Rust's learning curve is rather steep, and that the
119+
compiler messages are an important learning tool.
120+
- When talking about the compiler, call it `the compiler`, not `Rust` or
121+
`rustc`.
122+
123+
### Lint naming
124+
125+
From [RFC 0344], lint names should be consistent, with the following
126+
guidelines:
127+
128+
The basic rule is: the lint name should make sense when read as "allow
129+
*lint-name*" or "allow *lint-name* items". For example, "allow
130+
`deprecated` items" and "allow `dead_code`" makes sense, while "allow
131+
`unsafe_block`" is ungrammatical (should be plural).
132+
133+
- Lint names should state the bad thing being checked for, e.g. `deprecated`,
134+
so that `#[allow(deprecated)]` (items) reads correctly. Thus `ctypes` is not
135+
an appropriate name; `improper_ctypes` is.
136+
137+
- Lints that apply to arbitrary items (like the stability lints) should just
138+
mention what they check for: use `deprecated` rather than
139+
`deprecated_items`. This keeps lint names short. (Again, think "allow
140+
*lint-name* items".)
141+
142+
- If a lint applies to a specific grammatical class, mention that class and
143+
use the plural form: use `unused_variables` rather than `unused_variable`.
144+
This makes `#[allow(unused_variables)]` read correctly.
145+
146+
- Lints that catch unnecessary, unused, or useless aspects of code should use
147+
the term `unused`, e.g. `unused_imports`, `unused_typecasts`.
148+
149+
- Use snake case in the same way you would for function names.
150+
151+
[RFC 0344]: https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#lints
152+
153+
### Diagnostic levels
154+
155+
Guidelines for different diagnostic levels:
156+
157+
- `error`: emitted when the compiler detects a problem that makes it unable to
158+
compile the program, either because the program is invalid or the programmer
159+
has decided to make a specific `warning` into an error.
160+
161+
- `warning`: emitted when the compiler detects something odd about a program.
162+
Care should be taken when adding warnings to avoid warning fatigue, and
163+
avoid false-positives where there really isn't a problem with the code. Some
164+
examples of when it is appropriate to issue a warning:
165+
166+
- A situation where the user *should* take action, such as swap out a
167+
deprecated item, or use a `Result`, but otherwise doesn't prevent
168+
compilation.
169+
- Unnecessary syntax that can be removed without affecting the semantics of
170+
the code. For example, unused code, or unnecessary `unsafe`.
171+
- Code that is very likely to be incorrect, dangerous, or confusing, but the
172+
language technically allows, and is not ready or confident enough to make
173+
an error. For example `unused_comparisons` (out of bounds comparisons) or
174+
`bindings_with_variant_name` (the user likely did not intend to create a
175+
binding in a pattern).
176+
- [Future-incompatible lints](#future-incompatible), where something was
177+
accidentally or erroneously accepted in the past, but rejecting would
178+
cause excessive breakage in the ecosystem.
179+
- Stylistic choices. For example, camel or snake case, or the `dyn` trait
180+
warning in the 2018 edition. These have a high bar to be added, and should
181+
only be used in exceptional circumstances. Other stylistic choices should
182+
either be allow-by-default lints, or part of other tools like Clippy or
183+
rustfmt.
184+
185+
- `help`: emitted following an `error` or `warning` to give additional
186+
information to the user about how to solve their problem. The error or
187+
warning portion should *not* suggest how to fix the problem, only the "help"
188+
sub-diagnostic should.
189+
190+
- `note`: emitted to identify additional circumstances and parts of the code
191+
that caused the warning or error. For example, the borrow checker will note
192+
any previous conflicting borrows.
193+
194+
Not to be confused with *lint levels*, whose guidelines are:
195+
196+
- `forbid`: Lints should never default to `forbid`.
197+
- `deny`: Equivalent to `error` diagnostic level. Some examples:
198+
199+
- A future-incompatible or edition-based lint that has graduated from the
200+
warning level.
201+
- Something that has an extremely high confidence that is incorrect, but
202+
still want an escape hatch to allow it to pass.
203+
204+
- `warn`: Equivalent to the `warning` diagnostic level. See `warning` above
205+
for guidelines.
206+
- `allow`: Examples of the kinds of lints that should default to `allow`:
207+
208+
- The lint has a too high false positive rate.
209+
- The lint is too opinionated.
210+
- The lint is experimental.
211+
- The lint is used for enforcing something that is not normally enforced.
212+
For example, the `unsafe_code` lint can be used to prevent usage of unsafe
213+
code.
214+
215+
More information about lint levels can be found in the [rustc
216+
book][rustc-lint-levels] and the [reference][reference-diagnostics].
217+
218+
[reference-diagnostics]: https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#lint-check-attributes
219+
[rustc-lint-levels]: https://doc.rust-lang.org/nightly/rustc/lints/levels.html
220+
64221
## Helpful tips and options
65222

66223
### Finding the source of errors
@@ -373,6 +530,7 @@ If you need a combination of options that's not supported by the
373530
`declare_lint!` macro, you can always define your own static with a type of
374531
`&Lint` but this is currently linted against in the compiler tree.
375532

533+
<a id="future-incompatible"></a>
376534
#### Guidelines for creating a future incompatibility lint
377535

378536
- Create a lint defaulting to warn as normal, with ideally the same error

0 commit comments

Comments
 (0)