1*69942c0aSMiguel Ojeda // SPDX-License-Identifier: Apache-2.0 OR MIT 2*69942c0aSMiguel Ojeda 3808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 4808c999fSMiguel Ojeda use crate::buffer::Cursor; 5808c999fSMiguel Ojeda use crate::thread::ThreadBound; 6808c999fSMiguel Ojeda use proc_macro2::{ 7808c999fSMiguel Ojeda Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, 8808c999fSMiguel Ojeda }; 9808c999fSMiguel Ojeda #[cfg(feature = "printing")] 10808c999fSMiguel Ojeda use quote::ToTokens; 11808c999fSMiguel Ojeda use std::fmt::{self, Debug, Display}; 12808c999fSMiguel Ojeda use std::slice; 13808c999fSMiguel Ojeda use std::vec; 14808c999fSMiguel Ojeda 15808c999fSMiguel Ojeda /// The result of a Syn parser. 16808c999fSMiguel Ojeda pub type Result<T> = std::result::Result<T, Error>; 17808c999fSMiguel Ojeda 18808c999fSMiguel Ojeda /// Error returned when a Syn parser cannot parse the input tokens. 19808c999fSMiguel Ojeda /// 20808c999fSMiguel Ojeda /// # Error reporting in proc macros 21808c999fSMiguel Ojeda /// 22808c999fSMiguel Ojeda /// The correct way to report errors back to the compiler from a procedural 23808c999fSMiguel Ojeda /// macro is by emitting an appropriately spanned invocation of 24808c999fSMiguel Ojeda /// [`compile_error!`] in the generated code. This produces a better diagnostic 25808c999fSMiguel Ojeda /// message than simply panicking the macro. 26808c999fSMiguel Ojeda /// 27808c999fSMiguel Ojeda /// [`compile_error!`]: std::compile_error! 28808c999fSMiguel Ojeda /// 29808c999fSMiguel Ojeda /// When parsing macro input, the [`parse_macro_input!`] macro handles the 30808c999fSMiguel Ojeda /// conversion to `compile_error!` automatically. 31808c999fSMiguel Ojeda /// 32808c999fSMiguel Ojeda /// [`parse_macro_input!`]: crate::parse_macro_input! 33808c999fSMiguel Ojeda /// 34808c999fSMiguel Ojeda /// ``` 35808c999fSMiguel Ojeda /// # extern crate proc_macro; 36808c999fSMiguel Ojeda /// # 37808c999fSMiguel Ojeda /// use proc_macro::TokenStream; 38808c999fSMiguel Ojeda /// use syn::parse::{Parse, ParseStream, Result}; 39808c999fSMiguel Ojeda /// use syn::{parse_macro_input, ItemFn}; 40808c999fSMiguel Ojeda /// 41808c999fSMiguel Ojeda /// # const IGNORE: &str = stringify! { 42808c999fSMiguel Ojeda /// #[proc_macro_attribute] 43808c999fSMiguel Ojeda /// # }; 44808c999fSMiguel Ojeda /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { 45808c999fSMiguel Ojeda /// let args = parse_macro_input!(args as MyAttrArgs); 46808c999fSMiguel Ojeda /// let input = parse_macro_input!(input as ItemFn); 47808c999fSMiguel Ojeda /// 48808c999fSMiguel Ojeda /// /* ... */ 49808c999fSMiguel Ojeda /// # TokenStream::new() 50808c999fSMiguel Ojeda /// } 51808c999fSMiguel Ojeda /// 52808c999fSMiguel Ojeda /// struct MyAttrArgs { 53808c999fSMiguel Ojeda /// # _k: [(); { stringify! { 54808c999fSMiguel Ojeda /// ... 55808c999fSMiguel Ojeda /// # }; 0 }] 56808c999fSMiguel Ojeda /// } 57808c999fSMiguel Ojeda /// 58808c999fSMiguel Ojeda /// impl Parse for MyAttrArgs { 59808c999fSMiguel Ojeda /// fn parse(input: ParseStream) -> Result<Self> { 60808c999fSMiguel Ojeda /// # stringify! { 61808c999fSMiguel Ojeda /// ... 62808c999fSMiguel Ojeda /// # }; 63808c999fSMiguel Ojeda /// # unimplemented!() 64808c999fSMiguel Ojeda /// } 65808c999fSMiguel Ojeda /// } 66808c999fSMiguel Ojeda /// ``` 67808c999fSMiguel Ojeda /// 68808c999fSMiguel Ojeda /// For errors that arise later than the initial parsing stage, the 69808c999fSMiguel Ojeda /// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to 70808c999fSMiguel Ojeda /// perform an explicit conversion to `compile_error!`. 71808c999fSMiguel Ojeda /// 72808c999fSMiguel Ojeda /// [`.to_compile_error()`]: Error::to_compile_error 73808c999fSMiguel Ojeda /// [`.into_compile_error()`]: Error::into_compile_error 74808c999fSMiguel Ojeda /// 75808c999fSMiguel Ojeda /// ``` 76808c999fSMiguel Ojeda /// # extern crate proc_macro; 77808c999fSMiguel Ojeda /// # 78808c999fSMiguel Ojeda /// # use proc_macro::TokenStream; 79808c999fSMiguel Ojeda /// # use syn::{parse_macro_input, DeriveInput}; 80808c999fSMiguel Ojeda /// # 81808c999fSMiguel Ojeda /// # const IGNORE: &str = stringify! { 82808c999fSMiguel Ojeda /// #[proc_macro_derive(MyDerive)] 83808c999fSMiguel Ojeda /// # }; 84808c999fSMiguel Ojeda /// pub fn my_derive(input: TokenStream) -> TokenStream { 85808c999fSMiguel Ojeda /// let input = parse_macro_input!(input as DeriveInput); 86808c999fSMiguel Ojeda /// 87808c999fSMiguel Ojeda /// // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream> 88808c999fSMiguel Ojeda /// expand::my_derive(input) 89808c999fSMiguel Ojeda /// .unwrap_or_else(syn::Error::into_compile_error) 90808c999fSMiguel Ojeda /// .into() 91808c999fSMiguel Ojeda /// } 92808c999fSMiguel Ojeda /// # 93808c999fSMiguel Ojeda /// # mod expand { 94808c999fSMiguel Ojeda /// # use proc_macro2::TokenStream; 95808c999fSMiguel Ojeda /// # use syn::{DeriveInput, Result}; 96808c999fSMiguel Ojeda /// # 97808c999fSMiguel Ojeda /// # pub fn my_derive(input: DeriveInput) -> Result<TokenStream> { 98808c999fSMiguel Ojeda /// # unimplemented!() 99808c999fSMiguel Ojeda /// # } 100808c999fSMiguel Ojeda /// # } 101808c999fSMiguel Ojeda /// ``` 102808c999fSMiguel Ojeda pub struct Error { 103808c999fSMiguel Ojeda messages: Vec<ErrorMessage>, 104808c999fSMiguel Ojeda } 105808c999fSMiguel Ojeda 106808c999fSMiguel Ojeda struct ErrorMessage { 107808c999fSMiguel Ojeda // Span is implemented as an index into a thread-local interner to keep the 108808c999fSMiguel Ojeda // size small. It is not safe to access from a different thread. We want 109808c999fSMiguel Ojeda // errors to be Send and Sync to play nicely with ecosystem crates for error 110808c999fSMiguel Ojeda // handling, so pin the span we're given to its original thread and assume 111808c999fSMiguel Ojeda // it is Span::call_site if accessed from any other thread. 112808c999fSMiguel Ojeda span: ThreadBound<SpanRange>, 113808c999fSMiguel Ojeda message: String, 114808c999fSMiguel Ojeda } 115808c999fSMiguel Ojeda 116808c999fSMiguel Ojeda // Cannot use std::ops::Range<Span> because that does not implement Copy, 117808c999fSMiguel Ojeda // whereas ThreadBound<T> requires a Copy impl as a way to ensure no Drop impls 118808c999fSMiguel Ojeda // are involved. 119808c999fSMiguel Ojeda struct SpanRange { 120808c999fSMiguel Ojeda start: Span, 121808c999fSMiguel Ojeda end: Span, 122808c999fSMiguel Ojeda } 123808c999fSMiguel Ojeda 124808c999fSMiguel Ojeda #[cfg(test)] 125808c999fSMiguel Ojeda struct _Test 126808c999fSMiguel Ojeda where 127808c999fSMiguel Ojeda Error: Send + Sync; 128808c999fSMiguel Ojeda 129808c999fSMiguel Ojeda impl Error { 130808c999fSMiguel Ojeda /// Usually the [`ParseStream::error`] method will be used instead, which 131808c999fSMiguel Ojeda /// automatically uses the correct span from the current position of the 132808c999fSMiguel Ojeda /// parse stream. 133808c999fSMiguel Ojeda /// 134808c999fSMiguel Ojeda /// Use `Error::new` when the error needs to be triggered on some span other 135808c999fSMiguel Ojeda /// than where the parse stream is currently positioned. 136808c999fSMiguel Ojeda /// 137808c999fSMiguel Ojeda /// [`ParseStream::error`]: crate::parse::ParseBuffer::error 138808c999fSMiguel Ojeda /// 139808c999fSMiguel Ojeda /// # Example 140808c999fSMiguel Ojeda /// 141808c999fSMiguel Ojeda /// ``` 142808c999fSMiguel Ojeda /// use syn::{Error, Ident, LitStr, Result, Token}; 143808c999fSMiguel Ojeda /// use syn::parse::ParseStream; 144808c999fSMiguel Ojeda /// 145808c999fSMiguel Ojeda /// // Parses input that looks like `name = "string"` where the key must be 146808c999fSMiguel Ojeda /// // the identifier `name` and the value may be any string literal. 147808c999fSMiguel Ojeda /// // Returns the string literal. 148808c999fSMiguel Ojeda /// fn parse_name(input: ParseStream) -> Result<LitStr> { 149808c999fSMiguel Ojeda /// let name_token: Ident = input.parse()?; 150808c999fSMiguel Ojeda /// if name_token != "name" { 151808c999fSMiguel Ojeda /// // Trigger an error not on the current position of the stream, 152808c999fSMiguel Ojeda /// // but on the position of the unexpected identifier. 153808c999fSMiguel Ojeda /// return Err(Error::new(name_token.span(), "expected `name`")); 154808c999fSMiguel Ojeda /// } 155808c999fSMiguel Ojeda /// input.parse::<Token![=]>()?; 156808c999fSMiguel Ojeda /// let s: LitStr = input.parse()?; 157808c999fSMiguel Ojeda /// Ok(s) 158808c999fSMiguel Ojeda /// } 159808c999fSMiguel Ojeda /// ``` 160808c999fSMiguel Ojeda pub fn new<T: Display>(span: Span, message: T) -> Self { 161808c999fSMiguel Ojeda return new(span, message.to_string()); 162808c999fSMiguel Ojeda 163808c999fSMiguel Ojeda fn new(span: Span, message: String) -> Error { 164808c999fSMiguel Ojeda Error { 165808c999fSMiguel Ojeda messages: vec![ErrorMessage { 166808c999fSMiguel Ojeda span: ThreadBound::new(SpanRange { 167808c999fSMiguel Ojeda start: span, 168808c999fSMiguel Ojeda end: span, 169808c999fSMiguel Ojeda }), 170808c999fSMiguel Ojeda message, 171808c999fSMiguel Ojeda }], 172808c999fSMiguel Ojeda } 173808c999fSMiguel Ojeda } 174808c999fSMiguel Ojeda } 175808c999fSMiguel Ojeda 176808c999fSMiguel Ojeda /// Creates an error with the specified message spanning the given syntax 177808c999fSMiguel Ojeda /// tree node. 178808c999fSMiguel Ojeda /// 179808c999fSMiguel Ojeda /// Unlike the `Error::new` constructor, this constructor takes an argument 180808c999fSMiguel Ojeda /// `tokens` which is a syntax tree node. This allows the resulting `Error` 181808c999fSMiguel Ojeda /// to attempt to span all tokens inside of `tokens`. While you would 182808c999fSMiguel Ojeda /// typically be able to use the `Spanned` trait with the above `Error::new` 183808c999fSMiguel Ojeda /// constructor, implementation limitations today mean that 184808c999fSMiguel Ojeda /// `Error::new_spanned` may provide a higher-quality error message on 185808c999fSMiguel Ojeda /// stable Rust. 186808c999fSMiguel Ojeda /// 187808c999fSMiguel Ojeda /// When in doubt it's recommended to stick to `Error::new` (or 188808c999fSMiguel Ojeda /// `ParseStream::error`)! 189808c999fSMiguel Ojeda #[cfg(feature = "printing")] 190808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 191808c999fSMiguel Ojeda pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self { 192808c999fSMiguel Ojeda return new_spanned(tokens.into_token_stream(), message.to_string()); 193808c999fSMiguel Ojeda 194808c999fSMiguel Ojeda fn new_spanned(tokens: TokenStream, message: String) -> Error { 195808c999fSMiguel Ojeda let mut iter = tokens.into_iter(); 196808c999fSMiguel Ojeda let start = iter.next().map_or_else(Span::call_site, |t| t.span()); 197808c999fSMiguel Ojeda let end = iter.last().map_or(start, |t| t.span()); 198808c999fSMiguel Ojeda Error { 199808c999fSMiguel Ojeda messages: vec![ErrorMessage { 200808c999fSMiguel Ojeda span: ThreadBound::new(SpanRange { start, end }), 201808c999fSMiguel Ojeda message, 202808c999fSMiguel Ojeda }], 203808c999fSMiguel Ojeda } 204808c999fSMiguel Ojeda } 205808c999fSMiguel Ojeda } 206808c999fSMiguel Ojeda 207808c999fSMiguel Ojeda /// The source location of the error. 208808c999fSMiguel Ojeda /// 209808c999fSMiguel Ojeda /// Spans are not thread-safe so this function returns `Span::call_site()` 210808c999fSMiguel Ojeda /// if called from a different thread than the one on which the `Error` was 211808c999fSMiguel Ojeda /// originally created. 212808c999fSMiguel Ojeda pub fn span(&self) -> Span { 213808c999fSMiguel Ojeda let SpanRange { start, end } = match self.messages[0].span.get() { 214808c999fSMiguel Ojeda Some(span) => *span, 215808c999fSMiguel Ojeda None => return Span::call_site(), 216808c999fSMiguel Ojeda }; 217808c999fSMiguel Ojeda start.join(end).unwrap_or(start) 218808c999fSMiguel Ojeda } 219808c999fSMiguel Ojeda 220808c999fSMiguel Ojeda /// Render the error as an invocation of [`compile_error!`]. 221808c999fSMiguel Ojeda /// 222808c999fSMiguel Ojeda /// The [`parse_macro_input!`] macro provides a convenient way to invoke 223808c999fSMiguel Ojeda /// this method correctly in a procedural macro. 224808c999fSMiguel Ojeda /// 225808c999fSMiguel Ojeda /// [`compile_error!`]: std::compile_error! 226808c999fSMiguel Ojeda /// [`parse_macro_input!`]: crate::parse_macro_input! 227808c999fSMiguel Ojeda pub fn to_compile_error(&self) -> TokenStream { 228808c999fSMiguel Ojeda self.messages 229808c999fSMiguel Ojeda .iter() 230808c999fSMiguel Ojeda .map(ErrorMessage::to_compile_error) 231808c999fSMiguel Ojeda .collect() 232808c999fSMiguel Ojeda } 233808c999fSMiguel Ojeda 234808c999fSMiguel Ojeda /// Render the error as an invocation of [`compile_error!`]. 235808c999fSMiguel Ojeda /// 236808c999fSMiguel Ojeda /// [`compile_error!`]: std::compile_error! 237808c999fSMiguel Ojeda /// 238808c999fSMiguel Ojeda /// # Example 239808c999fSMiguel Ojeda /// 240808c999fSMiguel Ojeda /// ``` 241808c999fSMiguel Ojeda /// # extern crate proc_macro; 242808c999fSMiguel Ojeda /// # 243808c999fSMiguel Ojeda /// use proc_macro::TokenStream; 244808c999fSMiguel Ojeda /// use syn::{parse_macro_input, DeriveInput, Error}; 245808c999fSMiguel Ojeda /// 246808c999fSMiguel Ojeda /// # const _: &str = stringify! { 247808c999fSMiguel Ojeda /// #[proc_macro_derive(MyTrait)] 248808c999fSMiguel Ojeda /// # }; 249808c999fSMiguel Ojeda /// pub fn derive_my_trait(input: TokenStream) -> TokenStream { 250808c999fSMiguel Ojeda /// let input = parse_macro_input!(input as DeriveInput); 251808c999fSMiguel Ojeda /// my_trait::expand(input) 252808c999fSMiguel Ojeda /// .unwrap_or_else(Error::into_compile_error) 253808c999fSMiguel Ojeda /// .into() 254808c999fSMiguel Ojeda /// } 255808c999fSMiguel Ojeda /// 256808c999fSMiguel Ojeda /// mod my_trait { 257808c999fSMiguel Ojeda /// use proc_macro2::TokenStream; 258808c999fSMiguel Ojeda /// use syn::{DeriveInput, Result}; 259808c999fSMiguel Ojeda /// 260808c999fSMiguel Ojeda /// pub(crate) fn expand(input: DeriveInput) -> Result<TokenStream> { 261808c999fSMiguel Ojeda /// /* ... */ 262808c999fSMiguel Ojeda /// # unimplemented!() 263808c999fSMiguel Ojeda /// } 264808c999fSMiguel Ojeda /// } 265808c999fSMiguel Ojeda /// ``` 266808c999fSMiguel Ojeda pub fn into_compile_error(self) -> TokenStream { 267808c999fSMiguel Ojeda self.to_compile_error() 268808c999fSMiguel Ojeda } 269808c999fSMiguel Ojeda 270808c999fSMiguel Ojeda /// Add another error message to self such that when `to_compile_error()` is 271808c999fSMiguel Ojeda /// called, both errors will be emitted together. 272808c999fSMiguel Ojeda pub fn combine(&mut self, another: Error) { 273808c999fSMiguel Ojeda self.messages.extend(another.messages); 274808c999fSMiguel Ojeda } 275808c999fSMiguel Ojeda } 276808c999fSMiguel Ojeda 277808c999fSMiguel Ojeda impl ErrorMessage { 278808c999fSMiguel Ojeda fn to_compile_error(&self) -> TokenStream { 279808c999fSMiguel Ojeda let (start, end) = match self.span.get() { 280808c999fSMiguel Ojeda Some(range) => (range.start, range.end), 281808c999fSMiguel Ojeda None => (Span::call_site(), Span::call_site()), 282808c999fSMiguel Ojeda }; 283808c999fSMiguel Ojeda 284808c999fSMiguel Ojeda // ::core::compile_error!($message) 285808c999fSMiguel Ojeda TokenStream::from_iter([ 286808c999fSMiguel Ojeda TokenTree::Punct({ 287808c999fSMiguel Ojeda let mut punct = Punct::new(':', Spacing::Joint); 288808c999fSMiguel Ojeda punct.set_span(start); 289808c999fSMiguel Ojeda punct 290808c999fSMiguel Ojeda }), 291808c999fSMiguel Ojeda TokenTree::Punct({ 292808c999fSMiguel Ojeda let mut punct = Punct::new(':', Spacing::Alone); 293808c999fSMiguel Ojeda punct.set_span(start); 294808c999fSMiguel Ojeda punct 295808c999fSMiguel Ojeda }), 296808c999fSMiguel Ojeda TokenTree::Ident(Ident::new("core", start)), 297808c999fSMiguel Ojeda TokenTree::Punct({ 298808c999fSMiguel Ojeda let mut punct = Punct::new(':', Spacing::Joint); 299808c999fSMiguel Ojeda punct.set_span(start); 300808c999fSMiguel Ojeda punct 301808c999fSMiguel Ojeda }), 302808c999fSMiguel Ojeda TokenTree::Punct({ 303808c999fSMiguel Ojeda let mut punct = Punct::new(':', Spacing::Alone); 304808c999fSMiguel Ojeda punct.set_span(start); 305808c999fSMiguel Ojeda punct 306808c999fSMiguel Ojeda }), 307808c999fSMiguel Ojeda TokenTree::Ident(Ident::new("compile_error", start)), 308808c999fSMiguel Ojeda TokenTree::Punct({ 309808c999fSMiguel Ojeda let mut punct = Punct::new('!', Spacing::Alone); 310808c999fSMiguel Ojeda punct.set_span(start); 311808c999fSMiguel Ojeda punct 312808c999fSMiguel Ojeda }), 313808c999fSMiguel Ojeda TokenTree::Group({ 314808c999fSMiguel Ojeda let mut group = Group::new(Delimiter::Brace, { 315808c999fSMiguel Ojeda TokenStream::from_iter([TokenTree::Literal({ 316808c999fSMiguel Ojeda let mut string = Literal::string(&self.message); 317808c999fSMiguel Ojeda string.set_span(end); 318808c999fSMiguel Ojeda string 319808c999fSMiguel Ojeda })]) 320808c999fSMiguel Ojeda }); 321808c999fSMiguel Ojeda group.set_span(end); 322808c999fSMiguel Ojeda group 323808c999fSMiguel Ojeda }), 324808c999fSMiguel Ojeda ]) 325808c999fSMiguel Ojeda } 326808c999fSMiguel Ojeda } 327808c999fSMiguel Ojeda 328808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 329808c999fSMiguel Ojeda pub(crate) fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error { 330808c999fSMiguel Ojeda if cursor.eof() { 331808c999fSMiguel Ojeda Error::new(scope, format!("unexpected end of input, {}", message)) 332808c999fSMiguel Ojeda } else { 333808c999fSMiguel Ojeda let span = crate::buffer::open_span_of_group(cursor); 334808c999fSMiguel Ojeda Error::new(span, message) 335808c999fSMiguel Ojeda } 336808c999fSMiguel Ojeda } 337808c999fSMiguel Ojeda 338808c999fSMiguel Ojeda #[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))] 339808c999fSMiguel Ojeda pub(crate) fn new2<T: Display>(start: Span, end: Span, message: T) -> Error { 340808c999fSMiguel Ojeda return new2(start, end, message.to_string()); 341808c999fSMiguel Ojeda 342808c999fSMiguel Ojeda fn new2(start: Span, end: Span, message: String) -> Error { 343808c999fSMiguel Ojeda Error { 344808c999fSMiguel Ojeda messages: vec![ErrorMessage { 345808c999fSMiguel Ojeda span: ThreadBound::new(SpanRange { start, end }), 346808c999fSMiguel Ojeda message, 347808c999fSMiguel Ojeda }], 348808c999fSMiguel Ojeda } 349808c999fSMiguel Ojeda } 350808c999fSMiguel Ojeda } 351808c999fSMiguel Ojeda 352808c999fSMiguel Ojeda impl Debug for Error { 353808c999fSMiguel Ojeda fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 354808c999fSMiguel Ojeda if self.messages.len() == 1 { 355808c999fSMiguel Ojeda formatter 356808c999fSMiguel Ojeda .debug_tuple("Error") 357808c999fSMiguel Ojeda .field(&self.messages[0]) 358808c999fSMiguel Ojeda .finish() 359808c999fSMiguel Ojeda } else { 360808c999fSMiguel Ojeda formatter 361808c999fSMiguel Ojeda .debug_tuple("Error") 362808c999fSMiguel Ojeda .field(&self.messages) 363808c999fSMiguel Ojeda .finish() 364808c999fSMiguel Ojeda } 365808c999fSMiguel Ojeda } 366808c999fSMiguel Ojeda } 367808c999fSMiguel Ojeda 368808c999fSMiguel Ojeda impl Debug for ErrorMessage { 369808c999fSMiguel Ojeda fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 370808c999fSMiguel Ojeda Debug::fmt(&self.message, formatter) 371808c999fSMiguel Ojeda } 372808c999fSMiguel Ojeda } 373808c999fSMiguel Ojeda 374808c999fSMiguel Ojeda impl Display for Error { 375808c999fSMiguel Ojeda fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 376808c999fSMiguel Ojeda formatter.write_str(&self.messages[0].message) 377808c999fSMiguel Ojeda } 378808c999fSMiguel Ojeda } 379808c999fSMiguel Ojeda 380808c999fSMiguel Ojeda impl Clone for Error { 381808c999fSMiguel Ojeda fn clone(&self) -> Self { 382808c999fSMiguel Ojeda Error { 383808c999fSMiguel Ojeda messages: self.messages.clone(), 384808c999fSMiguel Ojeda } 385808c999fSMiguel Ojeda } 386808c999fSMiguel Ojeda } 387808c999fSMiguel Ojeda 388808c999fSMiguel Ojeda impl Clone for ErrorMessage { 389808c999fSMiguel Ojeda fn clone(&self) -> Self { 390808c999fSMiguel Ojeda ErrorMessage { 391808c999fSMiguel Ojeda span: self.span, 392808c999fSMiguel Ojeda message: self.message.clone(), 393808c999fSMiguel Ojeda } 394808c999fSMiguel Ojeda } 395808c999fSMiguel Ojeda } 396808c999fSMiguel Ojeda 397808c999fSMiguel Ojeda impl Clone for SpanRange { 398808c999fSMiguel Ojeda fn clone(&self) -> Self { 399808c999fSMiguel Ojeda *self 400808c999fSMiguel Ojeda } 401808c999fSMiguel Ojeda } 402808c999fSMiguel Ojeda 403808c999fSMiguel Ojeda impl Copy for SpanRange {} 404808c999fSMiguel Ojeda 405808c999fSMiguel Ojeda impl std::error::Error for Error {} 406808c999fSMiguel Ojeda 407808c999fSMiguel Ojeda impl From<LexError> for Error { 408808c999fSMiguel Ojeda fn from(err: LexError) -> Self { 409808c999fSMiguel Ojeda Error::new(err.span(), err) 410808c999fSMiguel Ojeda } 411808c999fSMiguel Ojeda } 412808c999fSMiguel Ojeda 413808c999fSMiguel Ojeda impl IntoIterator for Error { 414808c999fSMiguel Ojeda type Item = Error; 415808c999fSMiguel Ojeda type IntoIter = IntoIter; 416808c999fSMiguel Ojeda 417808c999fSMiguel Ojeda fn into_iter(self) -> Self::IntoIter { 418808c999fSMiguel Ojeda IntoIter { 419808c999fSMiguel Ojeda messages: self.messages.into_iter(), 420808c999fSMiguel Ojeda } 421808c999fSMiguel Ojeda } 422808c999fSMiguel Ojeda } 423808c999fSMiguel Ojeda 424808c999fSMiguel Ojeda pub struct IntoIter { 425808c999fSMiguel Ojeda messages: vec::IntoIter<ErrorMessage>, 426808c999fSMiguel Ojeda } 427808c999fSMiguel Ojeda 428808c999fSMiguel Ojeda impl Iterator for IntoIter { 429808c999fSMiguel Ojeda type Item = Error; 430808c999fSMiguel Ojeda 431808c999fSMiguel Ojeda fn next(&mut self) -> Option<Self::Item> { 432808c999fSMiguel Ojeda Some(Error { 433808c999fSMiguel Ojeda messages: vec![self.messages.next()?], 434808c999fSMiguel Ojeda }) 435808c999fSMiguel Ojeda } 436808c999fSMiguel Ojeda } 437808c999fSMiguel Ojeda 438808c999fSMiguel Ojeda impl<'a> IntoIterator for &'a Error { 439808c999fSMiguel Ojeda type Item = Error; 440808c999fSMiguel Ojeda type IntoIter = Iter<'a>; 441808c999fSMiguel Ojeda 442808c999fSMiguel Ojeda fn into_iter(self) -> Self::IntoIter { 443808c999fSMiguel Ojeda Iter { 444808c999fSMiguel Ojeda messages: self.messages.iter(), 445808c999fSMiguel Ojeda } 446808c999fSMiguel Ojeda } 447808c999fSMiguel Ojeda } 448808c999fSMiguel Ojeda 449808c999fSMiguel Ojeda pub struct Iter<'a> { 450808c999fSMiguel Ojeda messages: slice::Iter<'a, ErrorMessage>, 451808c999fSMiguel Ojeda } 452808c999fSMiguel Ojeda 453808c999fSMiguel Ojeda impl<'a> Iterator for Iter<'a> { 454808c999fSMiguel Ojeda type Item = Error; 455808c999fSMiguel Ojeda 456808c999fSMiguel Ojeda fn next(&mut self) -> Option<Self::Item> { 457808c999fSMiguel Ojeda Some(Error { 458808c999fSMiguel Ojeda messages: vec![self.messages.next()?.clone()], 459808c999fSMiguel Ojeda }) 460808c999fSMiguel Ojeda } 461808c999fSMiguel Ojeda } 462808c999fSMiguel Ojeda 463808c999fSMiguel Ojeda impl Extend<Error> for Error { 464808c999fSMiguel Ojeda fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T) { 465808c999fSMiguel Ojeda for err in iter { 466808c999fSMiguel Ojeda self.combine(err); 467808c999fSMiguel Ojeda } 468808c999fSMiguel Ojeda } 469808c999fSMiguel Ojeda } 470