diff options
| author | bors <bors@rust-lang.org> | 2018-09-09 13:27:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-09-09 13:27:44 +0000 |
| commit | 40fc8ba5f95125f307ef17f11ec02b3f5fdad562 (patch) | |
| tree | 4cf149c2ccf4ced464d567ef8e7f2075c51d8815 /src/libsyntax/parse | |
| parent | df6ba0c4acceb5f63090bb20bd23f29c4f439376 (diff) | |
| parent | 57d6ada91d7c2d9af1115ae515b000fda93b3c4e (diff) | |
| download | rust-40fc8ba5f95125f307ef17f11ec02b3f5fdad562.tar.gz rust-40fc8ba5f95125f307ef17f11ec02b3f5fdad562.zip | |
Auto merge of #53902 - dtolnay:group, r=petrochenkov
proc_macro::Group::span_open and span_close
Before this addition, every delimited group like `(`...`)` `[`...`]` `{`...`}` has only a single Span that covers the full source location from opening delimiter to closing delimiter. This makes it impossible for a procedural macro to trigger an error pointing to just the opening or closing delimiter. The Rust compiler does not seem to have the same limitation:
```rust
mod m {
type T =
}
```
```console
error: expected type, found `}`
--> src/main.rs:3:1
|
3 | }
| ^
```
On that same input, a procedural macro would be forced to trigger the error on the last token inside the block, on the entire block, or on the next token after the block, none of which is really what you want for an error like above.
This commit adds `group.span_open()` and `group.span_close()` which access the Span associated with just the opening delimiter and just the closing delimiter of the group. Relevant to Syn as we implement real error messages for when parsing fails in a procedural macro: https://github.com/dtolnay/syn/issues/476.
```diff
impl Group {
fn span(&self) -> Span;
+ fn span_open(&self) -> Span;
+ fn span_close(&self) -> Span;
}
```
Fixes #48187
r? @alexcrichton
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/lexer/tokentrees.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 6 |
4 files changed, 21 insertions, 19 deletions
diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index e6ad3b9203e..9e08fa232f1 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -11,7 +11,7 @@ use print::pprust::token_to_string; use parse::lexer::StringReader; use parse::{token, PResult}; -use tokenstream::{Delimited, TokenStream, TokenTree}; +use tokenstream::{Delimited, DelimSpan, TokenStream, TokenTree}; impl<'a> StringReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. @@ -85,7 +85,7 @@ impl<'a> StringReader<'a> { let tts = self.parse_token_trees_until_close_delim(); // Expand to cover the entire delimited token tree - let span = pre_span.with_hi(self.span.hi()); + let delim_span = DelimSpan::from_pair(pre_span, self.span); let sm = self.sess.source_map(); match self.token { @@ -158,7 +158,7 @@ impl<'a> StringReader<'a> { _ => {} } - Ok(TokenTree::Delimited(span, Delimited { + Ok(TokenTree::Delimited(delim_span, Delimited { delim, tts: tts.into(), }).into()) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 28d63399b44..5c6d5816a47 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -722,7 +722,7 @@ mod tests { use attr::first_attr_value_str_by_name; use parse; use print::pprust::item_to_string; - use tokenstream::{self, TokenTree}; + use tokenstream::{self, DelimSpan, TokenTree}; use util::parser_testing::string_to_stream; use util::parser_testing::{string_to_expr, string_to_item}; use with_globals; @@ -805,7 +805,7 @@ mod tests { TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(), TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(), TokenTree::Delimited( - sp(5, 14), + DelimSpan::from_pair(sp(5, 6), sp(13, 14)), tokenstream::Delimited { delim: token::DelimToken::Paren, tts: TokenStream::concat(vec![ @@ -817,7 +817,7 @@ mod tests { ]).into(), }).into(), TokenTree::Delimited( - sp(15, 21), + DelimSpan::from_pair(sp(15, 16), sp(20, 21)), tokenstream::Delimited { delim: token::DelimToken::Brace, tts: TokenStream::concat(vec![ diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5f80af77f49..f57fca2cfcf 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -54,7 +54,7 @@ use print::pprust; use ptr::P; use parse::PResult; use ThinVec; -use tokenstream::{self, Delimited, ThinTokenStream, TokenTree, TokenStream}; +use tokenstream::{self, Delimited, DelimSpan, ThinTokenStream, TokenTree, TokenStream}; use symbol::{Symbol, keywords}; use std::borrow::Cow; @@ -262,7 +262,7 @@ struct TokenCursor { #[derive(Clone)] struct TokenCursorFrame { delim: token::DelimToken, - span: Span, + span: DelimSpan, open_delim: bool, tree_cursor: tokenstream::Cursor, close_delim: bool, @@ -293,7 +293,7 @@ enum LastToken { } impl TokenCursorFrame { - fn new(sp: Span, delimited: &Delimited) -> Self { + fn new(sp: DelimSpan, delimited: &Delimited) -> Self { TokenCursorFrame { delim: delimited.delim, span: sp, @@ -311,13 +311,13 @@ impl TokenCursor { let tree = if !self.frame.open_delim { self.frame.open_delim = true; Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } - .open_tt(self.frame.span) + .open_tt(self.frame.span.open) } else if let Some(tree) = self.frame.tree_cursor.next() { tree } else if !self.frame.close_delim { self.frame.close_delim = true; Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } - .close_tt(self.frame.span) + .close_tt(self.frame.span.close) } else if let Some(frame) = self.stack.pop() { self.frame = frame; continue @@ -361,7 +361,8 @@ impl TokenCursor { num_of_hashes = cmp::max(num_of_hashes, count); } - let body = TokenTree::Delimited(sp, Delimited { + let delim_span = DelimSpan::from_single(sp); + let body = TokenTree::Delimited(delim_span, Delimited { delim: token::Bracket, tts: [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), TokenTree::Token(sp, token::Eq), @@ -370,7 +371,7 @@ impl TokenCursor { .iter().cloned().collect::<TokenStream>().into(), }); - self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(sp, &Delimited { + self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(delim_span, &Delimited { delim: token::NoDelim, tts: if doc_comment_style(&name.as_str()) == AttrStyle::Inner { [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body] @@ -560,7 +561,7 @@ impl<'a> Parser<'a> { root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(syntax_pos::DUMMY_SP, &Delimited { + frame: TokenCursorFrame::new(DelimSpan::dummy(), &Delimited { delim: token::NoDelim, tts: tokens.into(), }), @@ -1227,7 +1228,8 @@ impl<'a> Parser<'a> { } match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { - Some(TokenTree::Token(span, _)) | Some(TokenTree::Delimited(span, _)) => span, + Some(TokenTree::Token(span, _)) => span, + Some(TokenTree::Delimited(span, _)) => span.entire(), None => self.look_ahead_span(dist - 1), } } @@ -2788,7 +2790,7 @@ impl<'a> Parser<'a> { token::OpenDelim(..) => { let frame = mem::replace(&mut self.token_cursor.frame, self.token_cursor.stack.pop().unwrap()); - self.span = frame.span; + self.span = frame.span.entire(); self.bump(); TokenTree::Delimited(frame.span, Delimited { delim: frame.delim, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1d0c6b5317a..6e8014284ec 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -23,8 +23,7 @@ use symbol::keywords; use syntax::parse::parse_stream_from_source_str; use syntax_pos::{self, Span, FileName}; use syntax_pos::symbol::{self, Symbol}; -use tokenstream::{TokenStream, TokenTree}; -use tokenstream; +use tokenstream::{self, DelimSpan, TokenStream, TokenTree}; use std::{cmp, fmt}; use std::mem; @@ -825,7 +824,8 @@ fn prepend_attrs(sess: &ParseSess, // that it encompasses more than each token, but it hopefully is "good // enough" for now at least. builder.push(tokenstream::TokenTree::Token(attr.span, Pound)); - builder.push(tokenstream::TokenTree::Delimited(attr.span, tokens)); + let delim_span = DelimSpan::from_single(attr.span); + builder.push(tokenstream::TokenTree::Delimited(delim_span, tokens)); } builder.push(tokens.clone()); Some(builder.build()) |
