rust/compiler
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
..
rustc Auto merge of #148925 - madsmtm:jemalloc-perf, r=Kobzol 2025-11-23 20:34:07 +00:00
rustc_abi Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
rustc_arena Finish transition from semitransparent to semiopaque for rustc_macro_transparency 2026-01-08 19:14:45 +01:00
rustc_ast Implement incremental caching for derive macro expansions 2026-01-16 07:36:36 +01:00
rustc_ast_ir Implement &pin patterns and ref pin bindings 2025-11-10 09:57:08 +08:00
rustc_ast_lowering Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_ast_passes Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_ast_pretty rename eii-extern-target 2026-01-12 08:07:23 +01:00
rustc_attr_parsing Remove #[rustc_lint_diagnostics] 2026-01-19 17:40:42 +01:00
rustc_baked_icu_data Unify the configuration of the compiler docs 2025-11-05 11:25:27 +00:00
rustc_borrowck Rollup merge of #150879 - remove_diag_lints, r=Kivooeo 2026-01-19 20:53:20 +01:00
rustc_builtin_macros Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_codegen_cranelift Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_codegen_gcc Remove Deref/DerefMut impl for Providers. 2026-01-14 15:55:59 +11:00
rustc_codegen_llvm Auto merge of #151363 - JonathanBrouwer:rollup-yIXELnN, r=JonathanBrouwer 2026-01-19 13:09:33 +00:00
rustc_codegen_ssa Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_const_eval Rollup merge of #150879 - remove_diag_lints, r=Kivooeo 2026-01-19 20:53:20 +01:00
rustc_data_structures Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
rustc_driver Unify the configuration of the compiler docs 2025-11-05 11:25:27 +00:00
rustc_driver_impl Rollup merge of #150895 - rustc_colored_explain, r=Kivooeo 2026-01-19 20:53:21 +01:00
rustc_error_codes Port #[instruction_set] to attribute parser 2025-12-31 03:01:05 +01:00
rustc_error_messages Remove unused pop_span_label method 2025-11-21 14:16:12 +00:00
rustc_errors Rollup merge of #150895 - rustc_colored_explain, r=Kivooeo 2026-01-19 20:53:21 +01:00
rustc_expand Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_feature Remove #[rustc_lint_diagnostics] 2026-01-19 17:40:42 +01:00
rustc_fluent_macro move and rename proc_macro::tracked_{env::var,path::path} 2025-11-26 22:44:25 +01:00
rustc_fs_util Avoid using env::temp when linking a binary 2025-12-24 06:41:42 +00:00
rustc_graphviz change non-canonical clone impl to {*self}, fix some doc comments 2025-12-20 13:46:22 +00:00
rustc_hashes some cleanups in compiler 2025-10-12 08:08:30 +00:00
rustc_hir Remove #[rustc_lint_diagnostics] 2026-01-19 17:40:42 +01:00
rustc_hir_analysis Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_hir_id rustc_hir_id: Add a comment explaining why the crate exists 2025-08-20 15:04:00 -07:00
rustc_hir_pretty Introduce hir::ConstArgKind::Array 2026-01-10 12:41:50 +09:00
rustc_hir_typeck Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_incremental Implement incremental caching for derive macro expansions 2026-01-16 07:36:36 +01:00
rustc_index simplify words initialization using Rc::new_zeroed 2026-01-16 04:25:12 +05:30
rustc_index_macros Revert introduction of [workspace.dependencies]. 2025-09-02 19:12:54 +10:00
rustc_infer Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
rustc_interface Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_lexer lexer/parser: ensure deps use the same unicode version 2025-12-27 11:20:42 +01:00
rustc_lint Remove all usages of #[rustc_lint_diagnostics] 2026-01-19 17:39:54 +01:00
rustc_lint_defs Auto merge of #151056 - mejrs:do_not_recommend, r=JonathanBrouwer 2026-01-15 19:35:19 +00:00
rustc_llvm Rollup merge of #150511 - Sa4dUs:offload-inline, r=ZuseZ4 2025-12-31 14:30:48 +01:00
rustc_log Restrict sysroot crate imports to those defined in this repo. 2025-10-15 13:17:25 +01:00
rustc_macros Factor out diagnostic slug checking from DiagnosticDerive and LintDiagnosticDerive 2026-01-18 21:48:11 +01:00
rustc_metadata Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_middle Rollup merge of #150879 - remove_diag_lints, r=Kivooeo 2026-01-19 20:53:20 +01:00
rustc_mir_build Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_mir_dataflow Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
rustc_mir_transform Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_monomorphize Fix capitalization of error messages 2026-01-18 22:40:55 +01:00
rustc_next_trait_solver Auto merge of #150859 - nnethercote:opt-Canonicalizer-flag-checks, r=lcnr 2026-01-13 17:36:45 +00:00
rustc_parse Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_parse_format rustc_parse_format: improve diagnostics for unsupported python numeric grouping 2026-01-11 23:42:38 +05:30
rustc_passes Remove #[rustc_lint_diagnostics] 2026-01-19 17:40:42 +01:00
rustc_pattern_analysis Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_privacy Unify the configuration of the compiler docs 2025-11-05 11:25:27 +00:00
rustc_proc_macro Update literal-escaper version to 0.0.7 2026-01-08 14:10:33 +01:00
rustc_public Auto merge of #148766 - cjgillot:mir-const-runtime-checks, r=RalfJung,saethlin 2025-12-22 06:58:28 +00:00
rustc_public_bridge Overhaul filename handling for cross-compiler consistency 2025-12-12 07:33:09 +01:00
rustc_query_impl Use with_reduced_queries to avoid query cycles. 2026-01-16 19:21:35 +11:00
rustc_query_system Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_resolve Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_sanitizers Port #[cfi_encoding] to attribute parser 2025-12-21 22:11:33 +01:00
rustc_serialize Allow internal_features lint in doc tests 2025-11-05 11:25:29 +00:00
rustc_session Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_span Remove #[rustc_lint_diagnostics] 2026-01-19 17:40:42 +01:00
rustc_symbol_mangling Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase 2026-01-19 17:39:49 +01:00
rustc_target Rollup merge of #150966 - arch-powerpc64le, r=petrochenkov 2026-01-14 22:29:57 +01:00
rustc_thread_pool change non-canonical clone impl to {*self}, fix some doc comments 2025-12-20 13:46:22 +00:00
rustc_trait_selection Rollup merge of #150879 - remove_diag_lints, r=Kivooeo 2026-01-19 20:53:20 +01:00
rustc_traits implied bounds comments 2026-01-19 16:08:54 +00:00
rustc_transmute Clean up src/dst transmute mess. 2026-01-12 09:22:58 +11:00
rustc_ty_utils Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
rustc_type_ir Rollup merge of #150861 - folding-cleanups, r=lcnr 2026-01-12 13:32:07 +01:00
rustc_type_ir_macros Provide an extended framework for type visit, for use in rust-analyzer 2025-12-16 01:47:28 +02:00
rustc_windows_rc [win] Use find-msvc-tools instead of cc to find the linker and rc on Windows 2025-09-19 12:00:30 -07:00