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