Created
March 22, 2023 14:04
-
-
Save yvt/baa2ceb4ef99ee9df582b35dca97df03 to your computer and use it in GitHub Desktop.
Attach backtrace to "unexpected token" errors in `syn`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/discouraged.rs b/src/discouraged.rs | |
index fb98d633..059b7351 100644 | |
--- a/src/discouraged.rs | |
+++ b/src/discouraged.rs | |
@@ -170,7 +170,7 @@ impl<'a> Speculative for ParseBuffer<'a> { | |
match (fork_sp, self_sp) { | |
// Unexpected set on the fork, but not on `self`, copy it over. | |
(Some(span), None) => { | |
- self_unexp.set(Unexpected::Some(span)); | |
+ self_unexp.set(Unexpected::Some(span.0, span.1)); | |
} | |
// Unexpected unset. Use chain to propagate errors from fork. | |
(None, None) => { | |
diff --git a/src/parse.rs b/src/parse.rs | |
index 61a10d2b..d0ef2169 100644 | |
--- a/src/parse.rs | |
+++ b/src/parse.rs | |
@@ -268,7 +268,10 @@ impl<'a> Drop for ParseBuffer<'a> { | |
if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(self.cursor()) { | |
let (inner, old_span) = inner_unexpected(self); | |
if old_span.is_none() { | |
- inner.set(Unexpected::Some(unexpected_span)); | |
+ inner.set(Unexpected::Some( | |
+ unexpected_span, | |
+ Rc::new(std::backtrace::Backtrace::capture()), | |
+ )); | |
} | |
} | |
} | |
@@ -396,7 +399,7 @@ pub(crate) fn new_parse_buffer( | |
pub(crate) enum Unexpected { | |
None, | |
- Some(Span), | |
+ Some(Span, Rc<std::backtrace::Backtrace>), | |
Chain(Rc<Cell<Unexpected>>), | |
} | |
@@ -410,7 +413,7 @@ impl Clone for Unexpected { | |
fn clone(&self) -> Self { | |
match self { | |
Unexpected::None => Unexpected::None, | |
- Unexpected::Some(span) => Unexpected::Some(*span), | |
+ Unexpected::Some(span, bt) => Unexpected::Some(*span, bt.clone()), | |
Unexpected::Chain(next) => Unexpected::Chain(next.clone()), | |
} | |
} | |
@@ -425,12 +428,17 @@ fn cell_clone<T: Default + Clone>(cell: &Cell<T>) -> T { | |
ret | |
} | |
-fn inner_unexpected(buffer: &ParseBuffer) -> (Rc<Cell<Unexpected>>, Option<Span>) { | |
+fn inner_unexpected( | |
+ buffer: &ParseBuffer, | |
+) -> ( | |
+ Rc<Cell<Unexpected>>, | |
+ Option<(Span, Rc<std::backtrace::Backtrace>)>, | |
+) { | |
let mut unexpected = get_unexpected(buffer); | |
loop { | |
match cell_clone(&unexpected) { | |
Unexpected::None => return (unexpected, None), | |
- Unexpected::Some(span) => return (unexpected, Some(span)), | |
+ Unexpected::Some(span, bt) => return (unexpected, Some((span, bt))), | |
Unexpected::Chain(next) => unexpected = next, | |
} | |
} | |
@@ -1105,7 +1113,7 @@ impl<'a> ParseBuffer<'a> { | |
fn check_unexpected(&self) -> Result<()> { | |
match inner_unexpected(self).1 { | |
- Some(span) => Err(Error::new(span, "unexpected token")), | |
+ Some((span, bt)) => Err(Error::new(span, format_args!("unexpected token: {bt}"))), | |
None => Ok(()), | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment