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