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}