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