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, LintDiagnosticDerive};
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(LintDiagnostic)]`, which allows for lints to be specified as a struct,
55/// independent from the actual lint emitting code.
56///
57/// ```ignore (rust)
58/// #[derive(LintDiagnostic)]
59/// #[diag("unused attribute")]
60/// pub(crate) struct UnusedAttribute {
61///     #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")]
62///     pub this: Span,
63///     #[note("attribute also specified here")]
64///     pub other: Span,
65///     #[warning(
66///         "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
67///     )]
68///     pub warning: bool,
69/// }
70/// ```
71///
72/// Then, later, to emit the error:
73///
74/// ```ignore (rust)
75/// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute {
76///     ...
77/// });
78/// ```
79///
80/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
81/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
82pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
83    LintDiagnosticDerive::new(s).into_tokens()
84}
85
86/// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
87/// suggestions to be specified as a structs or enums, independent from the actual diagnostics
88/// emitting code or diagnostic derives.
89///
90/// ```ignore (rust)
91/// #[derive(Subdiagnostic)]
92/// pub(crate) enum BuiltinUnusedDocCommentSub {
93///     #[help("use `//` for a plain comment")]
94///     PlainHelp,
95///     #[help("use `/* */` for a plain comment")]
96///     BlockHelp,
97/// }
98/// ```
99/// Then, later, use the subdiagnostic in a diagnostic:
100///
101/// ```ignore (rust)
102/// #[derive(LintDiagnostic)]
103/// #[diag("unused doc comment")]
104/// pub(crate) struct BuiltinUnusedDocComment<'a> {
105///     pub kind: &'a str,
106///     #[label("rustdoc does not generate documentation for {$kind}")]
107///     pub label: Span,
108///     #[subdiagnostic]
109///     pub sub: BuiltinUnusedDocCommentSub,
110/// }
111/// ```
112pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
113    SubdiagnosticDerive::new().into_tokens(s)
114}