error.rs 14 KB

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