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