]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_macros/src/diagnostics/mod.rs
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / compiler / rustc_macros / src / diagnostics / mod.rs
1 mod diagnostic;
2 mod diagnostic_builder;
3 mod error;
4 mod fluent;
5 mod subdiagnostic;
6 mod utils;
7
8 use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
9 pub(crate) use fluent::fluent_messages;
10 use proc_macro2::TokenStream;
11 use quote::format_ident;
12 use subdiagnostic::SubdiagnosticDeriveBuilder;
13 use 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::{symbol::Ident, Span};
23 /// # extern crate rust_middle;
24 /// # use rustc_middle::ty::Ty;
25 /// #[derive(Diagnostic)]
26 /// #[diag(borrowck_move_out_of_borrow, code = "E0505")]
27 /// pub struct MoveOutOfBorrowError<'tcx> {
28 ///     pub name: Ident,
29 ///     pub ty: Ty<'tcx>,
30 ///     #[primary_span]
31 ///     #[label]
32 ///     pub span: Span,
33 ///     #[label(first_borrow_label)]
34 ///     pub first_borrow_span: Span,
35 ///     #[suggestion(code = "{name}.clone()")]
36 ///     pub clone_sugg: Option<(Span, Applicability)>
37 /// }
38 /// ```
39 ///
40 /// ```fluent
41 /// move_out_of_borrow = cannot move out of {$name} because it is borrowed
42 ///     .label = cannot move out of borrow
43 ///     .first_borrow_label = `{$ty}` first borrowed here
44 ///     .suggestion = consider cloning here
45 /// ```
46 ///
47 /// Then, later, to emit the error:
48 ///
49 /// ```ignore (rust)
50 /// sess.emit_err(MoveOutOfBorrowError {
51 ///     expected,
52 ///     actual,
53 ///     span,
54 ///     first_borrow_span,
55 ///     clone_sugg: Some(suggestion, Applicability::MachineApplicable),
56 /// });
57 /// ```
58 ///
59 /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
60 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
61 pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
62     DiagnosticDerive::new(format_ident!("diag"), format_ident!("handler"), s).into_tokens()
63 }
64
65 /// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct,
66 /// independent from the actual lint emitting code.
67 ///
68 /// ```ignore (rust)
69 /// #[derive(LintDiagnostic)]
70 /// #[diag(lint_atomic_ordering_invalid_fail_success)]
71 /// pub struct AtomicOrderingInvalidLint {
72 ///     method: Symbol,
73 ///     success_ordering: Symbol,
74 ///     fail_ordering: Symbol,
75 ///     #[label(fail_label)]
76 ///     fail_order_arg_span: Span,
77 ///     #[label(success_label)]
78 ///     #[suggestion(
79 ///         code = "std::sync::atomic::Ordering::{success_suggestion}",
80 ///         applicability = "maybe-incorrect"
81 ///     )]
82 ///     success_order_arg_span: Span,
83 /// }
84 /// ```
85 ///
86 /// ```fluent
87 /// lint_atomic_ordering_invalid_fail_success = `{$method}`'s success ordering must be at least as strong as its failure ordering
88 ///     .fail_label = `{$fail_ordering}` failure ordering
89 ///     .success_label = `{$success_ordering}` success ordering
90 ///     .suggestion = consider using `{$success_suggestion}` success ordering instead
91 /// ```
92 ///
93 /// Then, later, to emit the error:
94 ///
95 /// ```ignore (rust)
96 /// cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
97 ///     method,
98 ///     success_ordering,
99 ///     fail_ordering,
100 ///     fail_order_arg_span,
101 ///     success_order_arg_span,
102 /// });
103 /// ```
104 ///
105 /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
106 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
107 pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
108     LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens()
109 }
110
111 /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
112 /// suggestions to be specified as a structs or enums, independent from the actual diagnostics
113 /// emitting code or diagnostic derives.
114 ///
115 /// ```ignore (rust)
116 /// #[derive(Subdiagnostic)]
117 /// pub enum ExpectedIdentifierLabel<'tcx> {
118 ///     #[label(expected_identifier)]
119 ///     WithoutFound {
120 ///         #[primary_span]
121 ///         span: Span,
122 ///     }
123 ///     #[label(expected_identifier_found)]
124 ///     WithFound {
125 ///         #[primary_span]
126 ///         span: Span,
127 ///         found: String,
128 ///     }
129 /// }
130 ///
131 /// #[derive(Subdiagnostic)]
132 /// #[suggestion(style = "verbose",parser::raw_identifier)]
133 /// pub struct RawIdentifierSuggestion<'tcx> {
134 ///     #[primary_span]
135 ///     span: Span,
136 ///     #[applicability]
137 ///     applicability: Applicability,
138 ///     ident: Ident,
139 /// }
140 /// ```
141 ///
142 /// ```fluent
143 /// parser_expected_identifier = expected identifier
144 ///
145 /// parser_expected_identifier-found = expected identifier, found {$found}
146 ///
147 /// parser_raw_identifier = escape `{$ident}` to use it as an identifier
148 /// ```
149 ///
150 /// Then, later, to add the subdiagnostic:
151 ///
152 /// ```ignore (rust)
153 /// diag.subdiagnostic(ExpectedIdentifierLabel::WithoutFound { span });
154 ///
155 /// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
156 /// ```
157 pub fn session_subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
158     SubdiagnosticDeriveBuilder::new().into_tokens(s)
159 }