diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2017-07-19 21:54:01 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2017-07-20 21:27:22 -0700 |
| commit | e99d309c5695a2b5ad1ab44c06fd32ec506cebaa (patch) | |
| tree | 3f19403fe2ff9c67b2abb6f33c5730cf62abbed7 /src/libsyntax | |
| parent | cc800531cc79b76b37a1e0f1f58f807ea7aee68b (diff) | |
| download | rust-e99d309c5695a2b5ad1ab44c06fd32ec506cebaa.tar.gz rust-e99d309c5695a2b5ad1ab44c06fd32ec506cebaa.zip | |
Use the macro structure spans instead of the invocation
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/quoted.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/tokenstream.rs | 32 |
5 files changed, 51 insertions, 7 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d2e51c9cb48..dc0848176d6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1046,6 +1046,7 @@ impl<'feat> ExpansionConfig<'feat> { } // A Marker adds the given mark to the syntax context. +#[derive(Debug)] pub struct Marker(pub Mark); impl Folder for Marker { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index f786b1abb8a..c7aab95e1d4 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -119,8 +119,21 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), _ => cx.span_bug(sp, "malformed macro rhs"), }; + // rhs has holes ( `$id` and `$(...)` that need filled) - let tts = transcribe(cx, Some(named_matches), rhs); + let mut tts = transcribe(cx, Some(named_matches), rhs.clone()); + + // Replace all the tokens for the corresponding positions in the macro, to maintain + // proper positions in error reporting, while maintaining the macro_backtrace. + if rhs.len() == tts.len() { + tts = tts.map_pos(|i, tt| { + let mut tt = tt.clone(); + let mut sp = rhs[i].span(); + sp.ctxt = tt.span().ctxt; + tt.set_span(sp); + tt + }); + } if cx.trace_macros() { trace_macros_note(cx, sp, format!("to `{}`", tts)); diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 74fa85d130b..6fdcadd1dde 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -128,7 +128,7 @@ impl TokenTree { } } - /// Retrieve the TokenTree's span. + /// Retrieve the `TokenTree`'s span. pub fn span(&self) -> Span { match *self { TokenTree::Token(sp, _) | diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ae3edfcbf32..553cac80d82 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -150,7 +150,7 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>) lhs } -#[derive(Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] enum PrevTokenKind { DocComment, Comma, @@ -6090,8 +6090,7 @@ impl<'a> Parser<'a> { let (delim, tts) = self.expect_delimited_token_tree()?; if delim != token::Brace { if !self.eat(&token::Semi) { - let prev_span = self.prev_span; - self.span_err(prev_span, + self.span_err(self.prev_span, "macros that expand to items must either \ be surrounded with braces or followed by \ a semicolon"); @@ -6108,8 +6107,7 @@ impl<'a> Parser<'a> { match visibility { Visibility::Inherited => {} _ => { - let prev_span = self.prev_span; - return Err(self.span_fatal(prev_span, "unmatched visibility `pub`")); + return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`")); } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 8eee25405df..0014fd5e937 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -131,6 +131,15 @@ impl TokenTree { } } + /// Modify the `TokenTree`'s span inplace. + pub fn set_span(&mut self, span: Span) { + match *self { + TokenTree::Token(ref mut sp, _) | TokenTree::Delimited(ref mut sp, _) => { + *sp = span; + } + } + } + /// Indicates if the stream is a token that is equal to the provided token. pub fn eq_token(&self, t: Token) -> bool { match *self { @@ -190,6 +199,14 @@ impl PartialEq<TokenStream> for TokenStream { } impl TokenStream { + pub fn len(&self) -> usize { + if let TokenStreamKind::Stream(ref slice) = self.kind { + slice.len() + } else { + 0 + } + } + pub fn empty() -> TokenStream { TokenStream { kind: TokenStreamKind::Empty } } @@ -241,6 +258,21 @@ impl TokenStream { } } + pub fn map_pos<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream { + let mut trees = self.into_trees(); + let mut result = Vec::new(); + let mut i = 0; + while let Some(stream) = trees.next_as_stream() { + result.push(match stream.kind { + TokenStreamKind::Tree(tree) => f(i, tree).into(), + TokenStreamKind::JointTree(tree) => f(i, tree).joint(), + _ => unreachable!() + }); + i += 1; + } + TokenStream::concat(result) + } + pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream { let mut trees = self.into_trees(); let mut result = Vec::new(); |
