rust/compiler/rustc_errors/src
Jonathan Brouwer 8a22babce9
Rollup merge of #150895 - rustc_colored_explain, r=Kivooeo
rustc_errors: Add (heuristic) Syntax Highlighting for `rustc --explain`

This PR adds a feature that enables `rustc --explain <error>` to have syntax highlighted code blocks. Due to performance, size and complexity constraints, the highlighter is very heuristc, relying on conventions for capitalizations and such to infer what an identifier represents. The details for the implementation are specified below.
# Changes
1. Change `term::entrypoint` to `term::entrypoint_with_formatter`, which takes an optional third argument, which is a function pointer to a formatter. ([compiler/rustc_errors/src/markdown/mod.rs](https://github.com/rust-lang/rust/compare/main...JayanAXHF:rust:rustc_colored_explain?expand=1#diff-a6e139cadbc2e6922d816eb08f9e2c7b48304d09e6588227e2b70215c4f0725c))
2. Change `MdStream::write_anstream_buf` to be a wrapper around a new function, `MdStream::write_anstream_buf_with_formatter`, which takes a function pointer to a formatter. ([compiler/rustc_errors/src/markdown/mod.rs](https://github.com/rust-lang/rust/compare/main...JayanAXHF:rust:rustc_colored_explain?expand=1#diff-a6e139cadbc2e6922d816eb08f9e2c7b48304d09e6588227e2b70215c4f0725c))
3. Change [`compiler/rustc_driver_impl/src/lib.rs`](https://github.com/rust-lang/rust/compare/main...JayanAXHF:rust:rustc_colored_explain?expand=1#diff-39877a2556ea309c89384956740d5892a59cef024aa9473cce16bbdd99287937) to call `MdStream::write_anstream_buf_with_formatter` instead of `MdStream::write_anstream_buf`.
4. Add a `compiler/rustc_driver_impl/src/highlighter.rs` file, which contains the actual syntax highlighter.

# Implementation Details
1. The highlighter starts from the `highlight` function defined in `compiler/rustc_driver_impl/src/highlighter.rs`. It creates a new instance of the `Highlighter` struct, and calls its `highlight_rustc_lexer` function to start highlighting.
2. The `highlight_rustc_lexer` function uses `rustc_lexer` to lex the code into `Token`s. `rustc_lexer` was chosen since it preserves the newlines after scanning.
3. Based on the kind of token (`TokenKind`), we color the corresponding lexeme.
## Highlighter Implementation
### Identifiers
1. All identifiers that match a (non-exhaustive and minimal) list of keywords are coloured magenta.
2. An identifier that begins with a capital letter is assumed as a type. There is no distinction between a `Trait` and a type, since that would involve name resolution, and the parts of `rustc` that perform name resolution on code do not preserve the original formatting. (An attempt to use `rustc_parse`'s lexer and `TokenStream` was made, which was then printed with the pretty printer, but failed to preserve the formatting and was generally more complex to work with)
3. An identifier that is immediately followed by a parenthesis is recognized as a function identifier, and coloured blue.
## Literals
5. A `String` literal (or its corresponding `Raw`, `C` and `Byte` versions) is colored green.
6. All other literals are colored bright red (orange-esque)
## Everything Else

Everything else is colored bright white and dimmed, to create a grayish colour.

---
# Demo
<img width="1864" height="2136" alt="image" src="https://github.com/user-attachments/assets/b17d3a71-e641-4457-be85-5e5b1cea2954" />

<caption> Command: <code>rustc --explain E0520</code> </caption>

---
This description was not generated by an LLM (:p)

cc: @bjorn3
2026-01-19 20:53:21 +01:00
..
json stabilize annotate-snippet as default formatter 2025-12-16 11:20:27 +00:00
markdown feat: added syntax highlighting for code blocks in rustc --explain 2026-01-19 17:44:24 +05:30
annotate_snippet_emitter_writer.rs remove fixme & update stderr files 2025-12-16 13:23:48 +00:00
codes.rs remove duplicated columns from rustc_error_code::error_codes! 2025-09-27 12:29:54 +02:00
decorate_diag.rs Refactor lint buffering to avoid requiring a giant enum 2025-08-22 01:59:56 -07:00
diagnostic.rs Remove all usages of #[rustc_lint_diagnostics] 2026-01-19 17:39:54 +01:00
diagnostic_impls.rs Move IntoDiagArg earlier in the dependency chains 2025-08-20 15:01:13 -07:00
emitter.rs stabilize annotate-snippet as default formatter 2025-12-16 11:20:27 +00:00
error.rs Reformat use declarations. 2024-07-29 08:26:52 +10:00
json.rs stabilize annotate-snippet as default formatter 2025-12-16 11:20:27 +00:00
lib.rs Remove all usages of #[rustc_lint_diagnostics] 2026-01-19 17:39:54 +01:00
lock.rs Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
registry.rs Reformat use declarations. 2024-07-29 08:26:52 +10:00
snippet.rs Use abs_diff where applicable 2025-03-27 18:29:06 +00:00
styled_buffer.rs use let chains in ast, borrowck, codegen, const_eval 2025-07-28 06:08:48 +05:00
tests.rs Extract Translator struct 2025-06-19 13:02:04 -05:00
timings.rs Add codegen timing section 2025-06-23 08:50:17 +02:00
translation.rs Extract Translator struct 2025-06-19 13:02:04 -05:00