Skip to main content

rustc_macros/diagnostics/
mod.rs

1mod diagnostic;
2mod diagnostic_builder;
3mod error;
4mod message;
5mod msg_macro;
6mod subdiagnostic;
7mod utils;
8
9use diagnostic::DiagnosticDerive;
10pub(super) use msg_macro::msg_macro;
11use proc_macro2::TokenStream;
12use subdiagnostic::SubdiagnosticDerive;
13use synstructure::Structure;
14
15/// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
16/// independent from the actual diagnostics emitting code.
17///
18/// ```ignore (rust)
19/// # extern crate rustc_errors;
20/// # use rustc_errors::Applicability;
21/// # extern crate rustc_span;
22/// # use rustc_span::{Ident, Span};
23/// # extern crate rust_middle;
24/// # use rustc_middle::ty::Ty;
25/// #[derive(Diagnostic)]
26/// #[diag("this is an example message", code = E0123)]
27/// pub(crate) struct ExampleError<'tcx> {
28///     pub name: Ident,
29///     pub ty: Ty<'tcx>,
30///     #[primary_span]
31///     #[label("with a label")]
32///     pub span: Span,
33///     #[label("with a label")]
34///     pub other_span: Span,
35///     #[suggestion("with a suggestion", code = "{name}.clone()")]
36///     pub opt_sugg: Option<(Span, Applicability)>,
37/// }
38/// ```
39///
40/// Then, later, to emit the error:
41///
42/// ```ignore (rust)
43/// sess.emit_err(ExampleError {
44///     name, ty, span, other_span, opt_sugg
45/// });
46/// ```
47///
48/// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
49/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
50pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream {
51    DiagnosticDerive::new(s).into_tokens()
52}
53
54/// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
55/// suggestions to be specified as a structs or enums, independent from the actual diagnostics
56/// emitting code or diagnostic derives.
57///
58/// ```ignore (rust)
59/// #[derive(Subdiagnostic)]
60/// pub(crate) enum BuiltinUnusedDocCommentSub {
61///     #[help("use `//` for a plain comment")]
62///     PlainHelp,
63///     #[help("use `/* */` for a plain comment")]
64///     BlockHelp,
65/// }
66/// ```
67/// Then, later, use the subdiagnostic in a diagnostic:
68///
69/// ```ignore (rust)
70/// #[derive(Diagnostic)]
71/// #[diag("unused doc comment")]
72/// pub(crate) struct BuiltinUnusedDocComment<'a> {
73///     pub kind: &'a str,
74///     #[label("rustdoc does not generate documentation for {$kind}")]
75///     pub label: Span,
76///     #[subdiagnostic]
77///     pub sub: BuiltinUnusedDocCommentSub,
78/// }
79/// ```
80pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
81    SubdiagnosticDerive::new().into_tokens(s)
82}