1 #[cfg(feature = "parsing")]
2 use crate::buffer::Cursor;
3 use crate::thread::ThreadBound;
4 use proc_macro2::{
5     Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
6 };
7 #[cfg(feature = "printing")]
8 use quote::ToTokens;
9 use std::fmt::{self, Debug, Display};
10 use std::slice;
11 use std::vec;
12 
13 /// The result of a Syn parser.
14 pub type Result<T> = std::result::Result<T, Error>;
15 
16 /// Error returned when a Syn parser cannot parse the input tokens.
17 ///
18 /// # Error reporting in proc macros
19 ///
20 /// The correct way to report errors back to the compiler from a procedural
21 /// macro is by emitting an appropriately spanned invocation of
22 /// [`compile_error!`] in the generated code. This produces a better diagnostic
23 /// message than simply panicking the macro.
24 ///
25 /// [`compile_error!`]: std::compile_error!
26 ///
27 /// When parsing macro input, the [`parse_macro_input!`] macro handles the
28 /// conversion to `compile_error!` automatically.
29 ///
30 /// [`parse_macro_input!`]: crate::parse_macro_input!
31 ///
32 /// ```
33 /// # extern crate proc_macro;
34 /// #
35 /// use proc_macro::TokenStream;
36 /// use syn::parse::{Parse, ParseStream, Result};
37 /// use syn::{parse_macro_input, ItemFn};
38 ///
39 /// # const IGNORE: &str = stringify! {
40 /// #[proc_macro_attribute]
41 /// # };
42 /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
43 ///     let args = parse_macro_input!(args as MyAttrArgs);
44 ///     let input = parse_macro_input!(input as ItemFn);
45 ///
46 ///     /* ... */
47 ///     # TokenStream::new()
48 /// }
49 ///
50 /// struct MyAttrArgs {
51 ///     # _k: [(); { stringify! {
52 ///     ...
53 ///     # }; 0 }]
54 /// }
55 ///
56 /// impl Parse for MyAttrArgs {
57 ///     fn parse(input: ParseStream) -> Result<Self> {
58 ///         # stringify! {
59 ///         ...
60 ///         # };
61 ///         # unimplemented!()
62 ///     }
63 /// }
64 /// ```
65 ///
66 /// For errors that arise later than the initial parsing stage, the
67 /// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to
68 /// perform an explicit conversion to `compile_error!`.
69 ///
70 /// [`.to_compile_error()`]: Error::to_compile_error
71 /// [`.into_compile_error()`]: Error::into_compile_error
72 ///
73 /// ```
74 /// # extern crate proc_macro;
75 /// #
76 /// # use proc_macro::TokenStream;
77 /// # use syn::{parse_macro_input, DeriveInput};
78 /// #
79 /// # const IGNORE: &str = stringify! {
80 /// #[proc_macro_derive(MyDerive)]
81 /// # };
82 /// pub fn my_derive(input: TokenStream) -> TokenStream {
83 ///     let input = parse_macro_input!(input as DeriveInput);
84 ///
85 ///     // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
86 ///     expand::my_derive(input)
87 ///         .unwrap_or_else(syn::Error::into_compile_error)
88 ///         .into()
89 /// }
90 /// #
91 /// # mod expand {
92 /// #     use proc_macro2::TokenStream;
93 /// #     use syn::{DeriveInput, Result};
94 /// #
95 /// #     pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
96 /// #         unimplemented!()
97 /// #     }
98 /// # }
99 /// ```
100 pub struct Error {
101     messages: Vec<ErrorMessage>,
102 }
103 
104 struct ErrorMessage {
105     // Span is implemented as an index into a thread-local interner to keep the
106     // size small. It is not safe to access from a different thread. We want
107     // errors to be Send and Sync to play nicely with ecosystem crates for error
108     // handling, so pin the span we're given to its original thread and assume
109     // it is Span::call_site if accessed from any other thread.
110     span: ThreadBound<SpanRange>,
111     message: String,
112 }
113 
114 // Cannot use std::ops::Range<Span> because that does not implement Copy,
115 // whereas ThreadBound<T> requires a Copy impl as a way to ensure no Drop impls
116 // are involved.
117 struct SpanRange {
118     start: Span,
119     end: Span,
120 }
121 
122 #[cfg(test)]
123 struct _Test
124 where
125     Error: Send + Sync;
126 
127 impl Error {
128     /// Usually the [`ParseStream::error`] method will be used instead, which
129     /// automatically uses the correct span from the current position of the
130     /// parse stream.
131     ///
132     /// Use `Error::new` when the error needs to be triggered on some span other
133     /// than where the parse stream is currently positioned.
134     ///
135     /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
136     ///
137     /// # Example
138     ///
139     /// ```
140     /// use syn::{Error, Ident, LitStr, Result, Token};
141     /// use syn::parse::ParseStream;
142     ///
143     /// // Parses input that looks like `name = "string"` where the key must be
144     /// // the identifier `name` and the value may be any string literal.
145     /// // Returns the string literal.
146     /// fn parse_name(input: ParseStream) -> Result<LitStr> {
147     ///     let name_token: Ident = input.parse()?;
148     ///     if name_token != "name" {
149     ///         // Trigger an error not on the current position of the stream,
150     ///         // but on the position of the unexpected identifier.
151     ///         return Err(Error::new(name_token.span(), "expected `name`"));
152     ///     }
153     ///     input.parse::<Token![=]>()?;
154     ///     let s: LitStr = input.parse()?;
155     ///     Ok(s)
156     /// }
157     /// ```
new<T: Display>(span: Span, message: T) -> Self158     pub fn new<T: Display>(span: Span, message: T) -> Self {
159         return new(span, message.to_string());
160 
161         fn new(span: Span, message: String) -> Error {
162             Error {
163                 messages: vec![ErrorMessage {
164                     span: ThreadBound::new(SpanRange {
165                         start: span,
166                         end: span,
167                     }),
168                     message,
169                 }],
170             }
171         }
172     }
173 
174     /// Creates an error with the specified message spanning the given syntax
175     /// tree node.
176     ///
177     /// Unlike the `Error::new` constructor, this constructor takes an argument
178     /// `tokens` which is a syntax tree node. This allows the resulting `Error`
179     /// to attempt to span all tokens inside of `tokens`. While you would
180     /// typically be able to use the `Spanned` trait with the above `Error::new`
181     /// constructor, implementation limitations today mean that
182     /// `Error::new_spanned` may provide a higher-quality error message on
183     /// stable Rust.
184     ///
185     /// When in doubt it's recommended to stick to `Error::new` (or
186     /// `ParseStream::error`)!
187     #[cfg(feature = "printing")]
188     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self189     pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
190         return new_spanned(tokens.into_token_stream(), message.to_string());
191 
192         fn new_spanned(tokens: TokenStream, message: String) -> Error {
193             let mut iter = tokens.into_iter();
194             let start = iter.next().map_or_else(Span::call_site, |t| t.span());
195             let end = iter.last().map_or(start, |t| t.span());
196             Error {
197                 messages: vec![ErrorMessage {
198                     span: ThreadBound::new(SpanRange { start, end }),
199                     message,
200                 }],
201             }
202         }
203     }
204 
205     /// The source location of the error.
206     ///
207     /// Spans are not thread-safe so this function returns `Span::call_site()`
208     /// if called from a different thread than the one on which the `Error` was
209     /// originally created.
span(&self) -> Span210     pub fn span(&self) -> Span {
211         let SpanRange { start, end } = match self.messages[0].span.get() {
212             Some(span) => *span,
213             None => return Span::call_site(),
214         };
215         start.join(end).unwrap_or(start)
216     }
217 
218     /// Render the error as an invocation of [`compile_error!`].
219     ///
220     /// The [`parse_macro_input!`] macro provides a convenient way to invoke
221     /// this method correctly in a procedural macro.
222     ///
223     /// [`compile_error!`]: std::compile_error!
224     /// [`parse_macro_input!`]: crate::parse_macro_input!
to_compile_error(&self) -> TokenStream225     pub fn to_compile_error(&self) -> TokenStream {
226         self.messages
227             .iter()
228             .map(ErrorMessage::to_compile_error)
229             .collect()
230     }
231 
232     /// Render the error as an invocation of [`compile_error!`].
233     ///
234     /// [`compile_error!`]: std::compile_error!
235     ///
236     /// # Example
237     ///
238     /// ```
239     /// # extern crate proc_macro;
240     /// #
241     /// use proc_macro::TokenStream;
242     /// use syn::{parse_macro_input, DeriveInput, Error};
243     ///
244     /// # const _: &str = stringify! {
245     /// #[proc_macro_derive(MyTrait)]
246     /// # };
247     /// pub fn derive_my_trait(input: TokenStream) -> TokenStream {
248     ///     let input = parse_macro_input!(input as DeriveInput);
249     ///     my_trait::expand(input)
250     ///         .unwrap_or_else(Error::into_compile_error)
251     ///         .into()
252     /// }
253     ///
254     /// mod my_trait {
255     ///     use proc_macro2::TokenStream;
256     ///     use syn::{DeriveInput, Result};
257     ///
258     ///     pub(crate) fn expand(input: DeriveInput) -> Result<TokenStream> {
259     ///         /* ... */
260     ///         # unimplemented!()
261     ///     }
262     /// }
263     /// ```
into_compile_error(self) -> TokenStream264     pub fn into_compile_error(self) -> TokenStream {
265         self.to_compile_error()
266     }
267 
268     /// Add another error message to self such that when `to_compile_error()` is
269     /// called, both errors will be emitted together.
combine(&mut self, another: Error)270     pub fn combine(&mut self, another: Error) {
271         self.messages.extend(another.messages);
272     }
273 }
274 
275 impl ErrorMessage {
to_compile_error(&self) -> TokenStream276     fn to_compile_error(&self) -> TokenStream {
277         let (start, end) = match self.span.get() {
278             Some(range) => (range.start, range.end),
279             None => (Span::call_site(), Span::call_site()),
280         };
281 
282         // ::core::compile_error!($message)
283         TokenStream::from_iter(vec![
284             TokenTree::Punct({
285                 let mut punct = Punct::new(':', Spacing::Joint);
286                 punct.set_span(start);
287                 punct
288             }),
289             TokenTree::Punct({
290                 let mut punct = Punct::new(':', Spacing::Alone);
291                 punct.set_span(start);
292                 punct
293             }),
294             TokenTree::Ident(Ident::new("core", start)),
295             TokenTree::Punct({
296                 let mut punct = Punct::new(':', Spacing::Joint);
297                 punct.set_span(start);
298                 punct
299             }),
300             TokenTree::Punct({
301                 let mut punct = Punct::new(':', Spacing::Alone);
302                 punct.set_span(start);
303                 punct
304             }),
305             TokenTree::Ident(Ident::new("compile_error", start)),
306             TokenTree::Punct({
307                 let mut punct = Punct::new('!', Spacing::Alone);
308                 punct.set_span(start);
309                 punct
310             }),
311             TokenTree::Group({
312                 let mut group = Group::new(Delimiter::Brace, {
313                     TokenStream::from_iter(vec![TokenTree::Literal({
314                         let mut string = Literal::string(&self.message);
315                         string.set_span(end);
316                         string
317                     })])
318                 });
319                 group.set_span(end);
320                 group
321             }),
322         ])
323     }
324 }
325 
326 #[cfg(feature = "parsing")]
new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error327 pub(crate) fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
328     if cursor.eof() {
329         Error::new(scope, format!("unexpected end of input, {}", message))
330     } else {
331         let span = crate::buffer::open_span_of_group(cursor);
332         Error::new(span, message)
333     }
334 }
335 
336 #[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
new2<T: Display>(start: Span, end: Span, message: T) -> Error337 pub(crate) fn new2<T: Display>(start: Span, end: Span, message: T) -> Error {
338     return new2(start, end, message.to_string());
339 
340     fn new2(start: Span, end: Span, message: String) -> Error {
341         Error {
342             messages: vec![ErrorMessage {
343                 span: ThreadBound::new(SpanRange { start, end }),
344                 message,
345             }],
346         }
347     }
348 }
349 
350 impl Debug for Error {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result351     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
352         if self.messages.len() == 1 {
353             formatter
354                 .debug_tuple("Error")
355                 .field(&self.messages[0])
356                 .finish()
357         } else {
358             formatter
359                 .debug_tuple("Error")
360                 .field(&self.messages)
361                 .finish()
362         }
363     }
364 }
365 
366 impl Debug for ErrorMessage {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result367     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
368         Debug::fmt(&self.message, formatter)
369     }
370 }
371 
372 impl Display for Error {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result373     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
374         formatter.write_str(&self.messages[0].message)
375     }
376 }
377 
378 impl Clone for Error {
clone(&self) -> Self379     fn clone(&self) -> Self {
380         Error {
381             messages: self.messages.clone(),
382         }
383     }
384 }
385 
386 impl Clone for ErrorMessage {
clone(&self) -> Self387     fn clone(&self) -> Self {
388         ErrorMessage {
389             span: self.span,
390             message: self.message.clone(),
391         }
392     }
393 }
394 
395 impl Clone for SpanRange {
clone(&self) -> Self396     fn clone(&self) -> Self {
397         *self
398     }
399 }
400 
401 impl Copy for SpanRange {}
402 
403 impl std::error::Error for Error {}
404 
405 impl From<LexError> for Error {
from(err: LexError) -> Self406     fn from(err: LexError) -> Self {
407         Error::new(err.span(), err)
408     }
409 }
410 
411 impl IntoIterator for Error {
412     type Item = Error;
413     type IntoIter = IntoIter;
414 
into_iter(self) -> Self::IntoIter415     fn into_iter(self) -> Self::IntoIter {
416         IntoIter {
417             messages: self.messages.into_iter(),
418         }
419     }
420 }
421 
422 pub struct IntoIter {
423     messages: vec::IntoIter<ErrorMessage>,
424 }
425 
426 impl Iterator for IntoIter {
427     type Item = Error;
428 
next(&mut self) -> Option<Self::Item>429     fn next(&mut self) -> Option<Self::Item> {
430         Some(Error {
431             messages: vec![self.messages.next()?],
432         })
433     }
434 }
435 
436 impl<'a> IntoIterator for &'a Error {
437     type Item = Error;
438     type IntoIter = Iter<'a>;
439 
into_iter(self) -> Self::IntoIter440     fn into_iter(self) -> Self::IntoIter {
441         Iter {
442             messages: self.messages.iter(),
443         }
444     }
445 }
446 
447 pub struct Iter<'a> {
448     messages: slice::Iter<'a, ErrorMessage>,
449 }
450 
451 impl<'a> Iterator for Iter<'a> {
452     type Item = Error;
453 
next(&mut self) -> Option<Self::Item>454     fn next(&mut self) -> Option<Self::Item> {
455         Some(Error {
456             messages: vec![self.messages.next()?.clone()],
457         })
458     }
459 }
460 
461 impl Extend<Error> for Error {
extend<T: IntoIterator<Item = Error>>(&mut self, iter: T)462     fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T) {
463         for err in iter {
464             self.combine(err);
465         }
466     }
467 }
468