diff options
| author | bors <bors@rust-lang.org> | 2017-07-22 13:30:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-07-22 13:30:19 +0000 |
| commit | 35f64996ad5639173040097a0fe718e25d0dc29d (patch) | |
| tree | 007a6e8ff004824b69598715440cb0206b83cfd8 /src/libsyntax | |
| parent | e49a9483dedb3b9405dd04ac04d49a1196068347 (diff) | |
| parent | 6772661f37d6a6f88b95808fe957b8c6c15371f9 (diff) | |
| download | rust-35f64996ad5639173040097a0fe718e25d0dc29d.tar.gz rust-35f64996ad5639173040097a0fe718e25d0dc29d.zip | |
Auto merge of #43352 - estebank:macro-span-replacement, r=petrochenkov
Use the macro structure spans instead of the invocation Fix #42104, CC #2887.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 16 | ||||
| -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, 52 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..8e746676ecd 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -119,8 +119,22 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), _ => cx.span_bug(sp, "malformed macro rhs"), }; + + let rhs_spans = rhs.iter().map(|t| t.span()).collect::<Vec<_>>(); // 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); + + // 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_spans.len() == tts.len() { + tts = tts.map_enumerated(|i, tt| { + let mut tt = tt.clone(); + let mut sp = rhs_spans[i]; + 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..747bc7b4385 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_enumerated<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(); |
