|
| 1 | +# Error codes |
| 2 | +We generally try to assign each error message a unique code like `E0123`. These |
| 3 | +codes are defined in the compiler in the `diagnostics.rs` files found in each |
| 4 | +crate, which basically consist of macros. All error codes have an associated |
| 5 | +explanation: new error codes must include them. Note that not all _historical_ |
| 6 | +(no longer emitted) error codes have explanations. |
| 7 | + |
| 8 | +## Error explanations |
| 9 | + |
| 10 | +The explanations are written in Markdown (see the [CommonMark Spec] for |
| 11 | +specifics around syntax), and all of them are linked in the [`rustc_error_codes`] |
| 12 | +crate. Please read [RFC 1567] for details on how to format and write long error |
| 13 | +codes. As of <!-- date-check --> February 2023, there is an |
| 14 | +effort[^new-explanations] to replace this largely outdated RFC with a new more |
| 15 | +flexible standard. |
| 16 | + |
| 17 | +Error explanations should expand on the error message and provide details about |
| 18 | +_why_ the error occurs. It is not helpful for users to copy-paste a quick fix; |
| 19 | +explanations should help users understand why their code cannot be accepted by |
| 20 | +the compiler. Rust prides itself on helpful error messages and long-form |
| 21 | +explanations are no exception. However, before error explanations are |
| 22 | +overhauled[^new-explanations] it is a bit open as to how exactly they should be |
| 23 | +written, as always: ask your reviewer or ask around on the Rust Discord or Zulip. |
| 24 | + |
| 25 | +[^new-explanations]: See the draft RFC [here][new-explanations-rfc]. |
| 26 | + |
| 27 | +[`rustc_error_codes`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_codes/error_codes/index.html |
| 28 | +[CommonMark Spec]: https://spec.commonmark.org/current/ |
| 29 | +[RFC 1567]: https://github.com/rust-lang/rfcs/blob/master/text/1567-long-error-codes-explanation-normalization.md |
| 30 | +[new-explanations-rfc]: https://github.com/rust-lang/rfcs/pull/3370 |
| 31 | + |
| 32 | +## Allocating a fresh code |
| 33 | + |
| 34 | +Error codes are stored in `compiler/rustc_error_codes`. |
| 35 | + |
| 36 | +To create a new error, you first need to find the next available |
| 37 | +code. You can find it with `tidy`: |
| 38 | + |
| 39 | +``` |
| 40 | +./x.py test tidy |
| 41 | +``` |
| 42 | + |
| 43 | +This will invoke the tidy script, which generally checks that your code obeys |
| 44 | +our coding conventions. Some of these jobs check error codes and ensure that |
| 45 | +there aren't duplicates, etc (the tidy check is defined in |
| 46 | +`src/tools/tidy/src/error_codes.rs`). Once it is finished with that, tidy will |
| 47 | +print out the lowest unused code: |
| 48 | + |
| 49 | +``` |
| 50 | +... |
| 51 | +tidy check |
| 52 | +Found 505 error codes |
| 53 | +Highest error code: `E0591` |
| 54 | +... |
| 55 | +``` |
| 56 | + |
| 57 | +Here we see the highest error code in use is `E0591`, so we _probably_ want |
| 58 | +`E0592`. To be sure, run `rg E0592` and check, you should see no references. |
| 59 | + |
| 60 | +You will have to write an extended description for your error, |
| 61 | +which will go in `rustc_error_codes/src/error_codes/E0592.md`. |
| 62 | +To register the error, open `rustc_error_codes/src/error_codes.rs` and add the |
| 63 | +code (in its proper numerical order) into` register_diagnostics!` macro, like |
| 64 | +this: |
| 65 | + |
| 66 | +```rust |
| 67 | +register_diagnostics! { |
| 68 | + ... |
| 69 | + E0592: include_str!("./error_codes/E0592.md"), |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +To actually issue the error, you can use the `struct_span_err!` macro: |
| 74 | + |
| 75 | +```rust |
| 76 | +struct_span_err!(self.tcx.sess, // some path to the session here |
| 77 | + span, // whatever span in the source you want |
| 78 | + E0592, // your new error code |
| 79 | + fluent::example::an_error_message) |
| 80 | + .emit() // actually issue the error |
| 81 | +``` |
| 82 | + |
| 83 | +If you want to add notes or other snippets, you can invoke methods before you |
| 84 | +call `.emit()`: |
| 85 | + |
| 86 | +```rust |
| 87 | +struct_span_err!(...) |
| 88 | + .span_label(another_span, fluent::example::example_label) |
| 89 | + .span_note(another_span, fluent::example::separate_note) |
| 90 | + .emit_() |
| 91 | +``` |
| 92 | + |
| 93 | +For an example of a PR adding an error code, see [#76143]. |
| 94 | + |
| 95 | +[#76143]: https://github.com/rust-lang/rust/pull/76143 |
0 commit comments