proc_macro_error/
macros.rs

1// FIXME: this can be greatly simplified via $()?
2// as soon as MRSV hits 1.32
3
4/// Build [`Diagnostic`](struct.Diagnostic.html) instance from provided arguments.
5///
6/// # Syntax
7///
8/// See [the guide](index.html#guide).
9///
10#[macro_export]
11macro_rules! diagnostic {
12    // from alias
13    ($err:expr) => { $crate::Diagnostic::from($err) };
14
15    // span, message, help
16    ($span:expr, $level:expr, $fmt:expr, $($args:expr),+ ; $($rest:tt)+) => {{
17        #[allow(unused_imports)]
18        use $crate::__export::{
19            ToTokensAsSpanRange,
20            Span2AsSpanRange,
21            SpanAsSpanRange,
22            SpanRangeAsSpanRange
23        };
24        use $crate::DiagnosticExt;
25        let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
26
27        let diag = $crate::Diagnostic::spanned_range(
28            span_range,
29            $level,
30            format!($fmt, $($args),*)
31        );
32        $crate::__pme__suggestions!(diag $($rest)*);
33        diag
34    }};
35
36    ($span:expr, $level:expr, $msg:expr ; $($rest:tt)+) => {{
37        #[allow(unused_imports)]
38        use $crate::__export::{
39            ToTokensAsSpanRange,
40            Span2AsSpanRange,
41            SpanAsSpanRange,
42            SpanRangeAsSpanRange
43        };
44        use $crate::DiagnosticExt;
45        let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
46
47        let diag = $crate::Diagnostic::spanned_range(span_range, $level, $msg.to_string());
48        $crate::__pme__suggestions!(diag $($rest)*);
49        diag
50    }};
51
52    // span, message, no help
53    ($span:expr, $level:expr, $fmt:expr, $($args:expr),+) => {{
54        #[allow(unused_imports)]
55        use $crate::__export::{
56            ToTokensAsSpanRange,
57            Span2AsSpanRange,
58            SpanAsSpanRange,
59            SpanRangeAsSpanRange
60        };
61        use $crate::DiagnosticExt;
62        let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
63
64        $crate::Diagnostic::spanned_range(
65            span_range,
66            $level,
67            format!($fmt, $($args),*)
68        )
69    }};
70
71    ($span:expr, $level:expr, $msg:expr) => {{
72        #[allow(unused_imports)]
73        use $crate::__export::{
74            ToTokensAsSpanRange,
75            Span2AsSpanRange,
76            SpanAsSpanRange,
77            SpanRangeAsSpanRange
78        };
79        use $crate::DiagnosticExt;
80        let span_range = (&$span).FIRST_ARG_MUST_EITHER_BE_Span_OR_IMPLEMENT_ToTokens_OR_BE_SpanRange();
81
82        $crate::Diagnostic::spanned_range(span_range, $level, $msg.to_string())
83    }};
84
85
86    // trailing commas
87
88    ($span:expr, $level:expr, $fmt:expr, $($args:expr),+, ; $($rest:tt)+) => {
89        $crate::diagnostic!($span, $level, $fmt, $($args),* ; $($rest)*)
90    };
91    ($span:expr, $level:expr, $msg:expr, ; $($rest:tt)+) => {
92        $crate::diagnostic!($span, $level, $msg ; $($rest)*)
93    };
94    ($span:expr, $level:expr, $fmt:expr, $($args:expr),+,) => {
95        $crate::diagnostic!($span, $level, $fmt, $($args),*)
96    };
97    ($span:expr, $level:expr, $msg:expr,) => {
98        $crate::diagnostic!($span, $level, $msg)
99    };
100    // ($err:expr,) => { $crate::diagnostic!($err) };
101}
102
103/// Abort proc-macro execution right now and display the error.
104///
105/// # Syntax
106///
107/// See [the guide](index.html#guide).
108#[macro_export]
109macro_rules! abort {
110    ($err:expr) => {
111        $crate::diagnostic!($err).abort()
112    };
113
114    ($span:expr, $($tts:tt)*) => {
115        $crate::diagnostic!($span, $crate::Level::Error, $($tts)*).abort()
116    };
117}
118
119/// Shortcut for `abort!(Span::call_site(), msg...)`. This macro
120/// is still preferable over plain panic, panics are not for error reporting.
121///
122/// # Syntax
123///
124/// See [the guide](index.html#guide).
125///
126#[macro_export]
127macro_rules! abort_call_site {
128    ($($tts:tt)*) => {
129        $crate::abort!($crate::__export::proc_macro2::Span::call_site(), $($tts)*)
130    };
131}
132
133/// Emit an error while not aborting the proc-macro right away.
134///
135/// # Syntax
136///
137/// See [the guide](index.html#guide).
138///
139#[macro_export]
140macro_rules! emit_error {
141    ($err:expr) => {
142        $crate::diagnostic!($err).emit()
143    };
144
145    ($span:expr, $($tts:tt)*) => {{
146        let level = $crate::Level::Error;
147        $crate::diagnostic!($span, level, $($tts)*).emit()
148    }};
149}
150
151/// Shortcut for `emit_error!(Span::call_site(), ...)`. This macro
152/// is still preferable over plain panic, panics are not for error reporting..
153///
154/// # Syntax
155///
156/// See [the guide](index.html#guide).
157///
158#[macro_export]
159macro_rules! emit_call_site_error {
160    ($($tts:tt)*) => {
161        $crate::emit_error!($crate::__export::proc_macro2::Span::call_site(), $($tts)*)
162    };
163}
164
165/// Emit a warning. Warnings are not errors and compilation won't fail because of them.
166///
167/// **Does nothing on stable**
168///
169/// # Syntax
170///
171/// See [the guide](index.html#guide).
172///
173#[macro_export]
174macro_rules! emit_warning {
175    ($span:expr, $($tts:tt)*) => {
176        $crate::diagnostic!($span, $crate::Level::Warning, $($tts)*).emit()
177    };
178}
179
180/// Shortcut for `emit_warning!(Span::call_site(), ...)`.
181///
182/// **Does nothing on stable**
183///
184/// # Syntax
185///
186/// See [the guide](index.html#guide).
187///
188#[macro_export]
189macro_rules! emit_call_site_warning {
190    ($($tts:tt)*) => {{
191        $crate::emit_warning!($crate::__export::proc_macro2::Span::call_site(), $($tts)*)
192    }};
193}
194
195#[doc(hidden)]
196#[macro_export]
197macro_rules! __pme__suggestions {
198    ($var:ident) => ();
199
200    ($var:ident $help:ident =? $msg:expr) => {
201        let $var = if let Some(msg) = $msg {
202            $var.suggestion(stringify!($help), msg.to_string())
203        } else {
204            $var
205        };
206    };
207    ($var:ident $help:ident =? $span:expr => $msg:expr) => {
208        let $var = if let Some(msg) = $msg {
209            $var.span_suggestion($span.into(), stringify!($help), msg.to_string())
210        } else {
211            $var
212        };
213    };
214
215    ($var:ident $help:ident =? $msg:expr ; $($rest:tt)*) => {
216        $crate::__pme__suggestions!($var $help =? $msg);
217        $crate::__pme__suggestions!($var $($rest)*);
218    };
219    ($var:ident $help:ident =? $span:expr => $msg:expr ; $($rest:tt)*) => {
220        $crate::__pme__suggestions!($var $help =? $span => $msg);
221        $crate::__pme__suggestions!($var $($rest)*);
222    };
223
224
225    ($var:ident $help:ident = $msg:expr) => {
226        let $var = $var.suggestion(stringify!($help), $msg.to_string());
227    };
228    ($var:ident $help:ident = $fmt:expr, $($args:expr),+) => {
229        let $var = $var.suggestion(
230            stringify!($help),
231            format!($fmt, $($args),*)
232        );
233    };
234    ($var:ident $help:ident = $span:expr => $msg:expr) => {
235        let $var = $var.span_suggestion($span.into(), stringify!($help), $msg.to_string());
236    };
237    ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+) => {
238        let $var = $var.span_suggestion(
239            $span.into(),
240            stringify!($help),
241            format!($fmt, $($args),*)
242        );
243    };
244
245    ($var:ident $help:ident = $msg:expr ; $($rest:tt)*) => {
246        $crate::__pme__suggestions!($var $help = $msg);
247        $crate::__pme__suggestions!($var $($rest)*);
248    };
249    ($var:ident $help:ident = $fmt:expr, $($args:expr),+ ; $($rest:tt)*) => {
250        $crate::__pme__suggestions!($var $help = $fmt, $($args),*);
251        $crate::__pme__suggestions!($var $($rest)*);
252    };
253    ($var:ident $help:ident = $span:expr => $msg:expr ; $($rest:tt)*) => {
254        $crate::__pme__suggestions!($var $help = $span => $msg);
255        $crate::__pme__suggestions!($var $($rest)*);
256    };
257    ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+ ; $($rest:tt)*) => {
258        $crate::__pme__suggestions!($var $help = $span => $fmt, $($args),*);
259        $crate::__pme__suggestions!($var $($rest)*);
260    };
261
262    // trailing commas
263
264    ($var:ident $help:ident = $msg:expr,) => {
265        $crate::__pme__suggestions!($var $help = $msg)
266    };
267    ($var:ident $help:ident = $fmt:expr, $($args:expr),+,) => {
268        $crate::__pme__suggestions!($var $help = $fmt, $($args)*)
269    };
270    ($var:ident $help:ident = $span:expr => $msg:expr,) => {
271        $crate::__pme__suggestions!($var $help = $span => $msg)
272    };
273    ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),*,) => {
274        $crate::__pme__suggestions!($var $help = $span => $fmt, $($args)*)
275    };
276    ($var:ident $help:ident = $msg:expr, ; $($rest:tt)*) => {
277        $crate::__pme__suggestions!($var $help = $msg; $($rest)*)
278    };
279    ($var:ident $help:ident = $fmt:expr, $($args:expr),+, ; $($rest:tt)*) => {
280        $crate::__pme__suggestions!($var $help = $fmt, $($args),*; $($rest)*)
281    };
282    ($var:ident $help:ident = $span:expr => $msg:expr, ; $($rest:tt)*) => {
283        $crate::__pme__suggestions!($var $help = $span => $msg; $($rest)*)
284    };
285    ($var:ident $help:ident = $span:expr => $fmt:expr, $($args:expr),+, ; $($rest:tt)*) => {
286        $crate::__pme__suggestions!($var $help = $span => $fmt, $($args),*; $($rest)*)
287    };
288}