Skip to content

Commit 8fde04b

Browse files
committed
Improve Path spans.
1 parent f08d5ad commit 8fde04b

File tree

9 files changed

+95
-67
lines changed

9 files changed

+95
-67
lines changed

src/libsyntax/attr.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1015,9 +1015,10 @@ impl MetaItem {
10151015
{
10161016
let (mut span, name) = match tokens.next() {
10171017
Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name),
1018-
Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => return match **nt {
1019-
token::Nonterminal::NtMeta(ref meta) => Some(meta.clone()),
1020-
_ => None,
1018+
Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match **nt {
1019+
token::Nonterminal::NtIdent(ident) => (ident.span, ident.node.name),
1020+
token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
1021+
_ => return None,
10211022
},
10221023
_ => return None,
10231024
};

src/libsyntax/ext/base.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,26 @@ impl<F> TTMacroExpander for F
209209
{
210210
fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, input: TokenStream)
211211
-> Box<MacResult+'cx> {
212-
(*self)(ecx, span, &input.trees().collect::<Vec<_>>())
212+
struct AvoidInterpolatedIdents;
213+
214+
impl Folder for AvoidInterpolatedIdents {
215+
fn fold_tt(&mut self, tt: tokenstream::TokenTree) -> tokenstream::TokenTree {
216+
if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt {
217+
if let token::NtIdent(ident) = **nt {
218+
return tokenstream::TokenTree::Token(ident.span, token::Ident(ident.node));
219+
}
220+
}
221+
fold::noop_fold_tt(tt, self)
222+
}
223+
224+
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
225+
fold::noop_fold_mac(mac, self)
226+
}
227+
}
228+
229+
let input: Vec<_> =
230+
input.trees().map(|tt| AvoidInterpolatedIdents.fold_tt(tt)).collect();
231+
(*self)(ecx, span, &input)
213232
}
214233
}
215234

src/libsyntax/ext/tt/macro_parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
492492
_ => {}
493493
}
494494
// check at the beginning and the parser checks after each bump
495-
p.check_unknown_macro_variable();
495+
p.process_potential_macro_variable();
496496
match name {
497497
"item" => match panictry!(p.parse_item()) {
498498
Some(i) => token::NtItem(i),

src/libsyntax/ext/tt/macro_rules.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
121121
p.root_module_name = cx.current_expansion.module.mod_path.last()
122122
.map(|id| id.name.as_str().to_string());
123123

124-
p.check_unknown_macro_variable();
124+
p.process_potential_macro_variable();
125125
// Let the context choose how to interpret the result.
126126
// Weird, but useful for X-macros.
127127
return Box::new(ParserAnyMacro {

src/libsyntax/ext/tt/quoted.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,14 @@ pub fn parse(input: tokenstream::TokenStream, expect_matchers: bool, sess: &Pars
136136
TokenTree::Token(start_sp, token::SubstNt(ident)) if expect_matchers => {
137137
let span = match trees.next() {
138138
Some(tokenstream::TokenTree::Token(span, token::Colon)) => match trees.next() {
139-
Some(tokenstream::TokenTree::Token(end_sp, token::Ident(kind))) => {
140-
let span = Span { lo: start_sp.lo, ..end_sp };
141-
result.push(TokenTree::MetaVarDecl(span, ident, kind));
142-
continue
143-
}
139+
Some(tokenstream::TokenTree::Token(end_sp, ref tok)) => match tok.ident() {
140+
Some(kind) => {
141+
let span = Span { lo: start_sp.lo, ..end_sp };
142+
result.push(TokenTree::MetaVarDecl(span, ident, kind));
143+
continue
144+
}
145+
_ => end_sp,
146+
},
144147
tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(span),
145148
},
146149
tree @ _ => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp),

src/libsyntax/ext/tt/transcribe.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use ast::Ident;
1212
use errors::Handler;
1313
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
1414
use ext::tt::quoted;
15-
use parse::token::{self, SubstNt, Token, NtIdent, NtTT};
15+
use parse::token::{self, SubstNt, Token, NtTT};
1616
use syntax_pos::{Span, DUMMY_SP};
1717
use tokenstream::{TokenStream, TokenTree, Delimited};
1818
use util::small_vector::SmallVector;
@@ -154,13 +154,6 @@ pub fn transcribe(sp_diag: &Handler,
154154
None => result.push(TokenTree::Token(sp, SubstNt(ident)).into()),
155155
Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched {
156156
match **nt {
157-
// sidestep the interpolation tricks for ident because
158-
// (a) idents can be in lots of places, so it'd be a pain
159-
// (b) we actually can, since it's a token.
160-
NtIdent(ref sn) => {
161-
let token = TokenTree::Token(sn.span, token::Ident(sn.node));
162-
result.push(token.into());
163-
}
164157
NtTT(ref tt) => result.push(tt.clone().into()),
165158
_ => {
166159
let token = TokenTree::Token(sp, token::Interpolated(nt.clone()));

src/libsyntax/parse/mod.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,7 @@ pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc<FileMap>) -> TokenStream
218218

219219
/// Given stream and the ParseSess, produce a parser
220220
pub fn stream_to_parser<'a>(sess: &'a ParseSess, stream: TokenStream) -> Parser<'a> {
221-
let mut p = Parser::new(sess, stream, None, false);
222-
p.check_unknown_macro_variable();
223-
p
221+
Parser::new(sess, stream, None, false)
224222
}
225223

226224
/// Parse a string representing a character literal into its final form.

src/libsyntax/parse/parser.rs

+35-21
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ pub struct Parser<'a> {
160160
/// the span of the current token:
161161
pub span: Span,
162162
/// the span of the previous token:
163+
pub meta_var_span: Option<Span>,
163164
pub prev_span: Span,
164165
/// the previous token kind
165166
prev_token_kind: PrevTokenKind,
@@ -417,6 +418,7 @@ impl<'a> Parser<'a> {
417418
token: token::Underscore,
418419
span: syntax_pos::DUMMY_SP,
419420
prev_span: syntax_pos::DUMMY_SP,
421+
meta_var_span: None,
420422
prev_token_kind: PrevTokenKind::Other,
421423
restrictions: Restrictions::empty(),
422424
obsolete_set: HashSet::new(),
@@ -443,6 +445,7 @@ impl<'a> Parser<'a> {
443445
parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
444446
parser.directory.path.pop();
445447
}
448+
parser.process_potential_macro_variable();
446449
parser
447450
}
448451

@@ -1012,7 +1015,7 @@ impl<'a> Parser<'a> {
10121015
self.bug("attempted to bump the parser past EOF (may be stuck in a loop)");
10131016
}
10141017

1015-
self.prev_span = self.span;
1018+
self.prev_span = self.meta_var_span.take().unwrap_or(self.span);
10161019

10171020
// Record last token kind for possible error recovery.
10181021
self.prev_token_kind = match self.token {
@@ -1028,7 +1031,7 @@ impl<'a> Parser<'a> {
10281031
self.token = next.tok;
10291032
self.expected_tokens.clear();
10301033
// check after each token
1031-
self.check_unknown_macro_variable();
1034+
self.process_potential_macro_variable();
10321035
}
10331036

10341037
/// Advance the parser using provided token as a next one. Use this when
@@ -1722,7 +1725,7 @@ impl<'a> Parser<'a> {
17221725
pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
17231726
maybe_whole!(self, NtPath, |x| x);
17241727

1725-
let lo = self.span;
1728+
let lo = self.meta_var_span.unwrap_or(self.span);
17261729
let is_global = self.eat(&token::ModSep);
17271730

17281731
// Parse any number of segments and bound sets. A segment is an
@@ -1744,13 +1747,9 @@ impl<'a> Parser<'a> {
17441747
segments.insert(0, PathSegment::crate_root());
17451748
}
17461749

1747-
// Assemble the span.
1748-
// FIXME(#39450) This is bogus if part of the path is macro generated.
1749-
let span = lo.to(self.prev_span);
1750-
17511750
// Assemble the result.
17521751
Ok(ast::Path {
1753-
span: span,
1752+
span: lo.to(self.prev_span),
17541753
segments: segments,
17551754
})
17561755
}
@@ -1763,8 +1762,8 @@ impl<'a> Parser<'a> {
17631762
let mut segments = Vec::new();
17641763
loop {
17651764
// First, parse an identifier.
1765+
let ident_span = self.span;
17661766
let identifier = self.parse_path_segment_ident()?;
1767-
let ident_span = self.prev_span;
17681767

17691768
if self.check(&token::ModSep) && self.look_ahead(1, |t| *t == token::Lt) {
17701769
self.bump();
@@ -1831,8 +1830,8 @@ impl<'a> Parser<'a> {
18311830
let mut segments = Vec::new();
18321831
loop {
18331832
// First, parse an identifier.
1833+
let ident_span = self.span;
18341834
let identifier = self.parse_path_segment_ident()?;
1835-
let ident_span = self.prev_span;
18361835

18371836
// If we do not see a `::`, stop.
18381837
if !self.eat(&token::ModSep) {
@@ -1873,10 +1872,11 @@ impl<'a> Parser<'a> {
18731872
let mut segments = Vec::new();
18741873
loop {
18751874
// First, parse an identifier.
1875+
let ident_span = self.span;
18761876
let identifier = self.parse_path_segment_ident()?;
18771877

18781878
// Assemble and push the result.
1879-
segments.push(PathSegment::from_ident(identifier, self.prev_span));
1879+
segments.push(PathSegment::from_ident(identifier, ident_span));
18801880

18811881
// If we do not see a `::` or see `::{`/`::*`, stop.
18821882
if !self.check(&token::ModSep) || self.is_import_coupler() {
@@ -1896,8 +1896,9 @@ impl<'a> Parser<'a> {
18961896
fn expect_lifetime(&mut self) -> Lifetime {
18971897
match self.token {
18981898
token::Lifetime(ident) => {
1899+
let ident_span = self.span;
18991900
self.bump();
1900-
Lifetime { name: ident.name, span: self.prev_span, id: ast::DUMMY_NODE_ID }
1901+
Lifetime { name: ident.name, span: ident_span, id: ast::DUMMY_NODE_ID }
19011902
}
19021903
_ => self.span_bug(self.span, "not a lifetime")
19031904
}
@@ -2568,10 +2569,23 @@ impl<'a> Parser<'a> {
25682569
return Ok(e);
25692570
}
25702571

2571-
pub fn check_unknown_macro_variable(&mut self) {
2572-
if let token::SubstNt(name) = self.token {
2573-
self.fatal(&format!("unknown macro variable `{}`", name)).emit()
2574-
}
2572+
pub fn process_potential_macro_variable(&mut self) {
2573+
let ident = match self.token {
2574+
token::SubstNt(name) => {
2575+
self.fatal(&format!("unknown macro variable `{}`", name)).emit();
2576+
return
2577+
}
2578+
token::Interpolated(ref nt) => {
2579+
self.meta_var_span = Some(self.span);
2580+
match **nt {
2581+
token::NtIdent(ident) => ident,
2582+
_ => return,
2583+
}
2584+
}
2585+
_ => return,
2586+
};
2587+
self.token = token::Ident(ident.node);
2588+
self.span = ident.span;
25752589
}
25762590

25772591
/// parse a single token tree from the input.
@@ -2589,9 +2603,9 @@ impl<'a> Parser<'a> {
25892603
},
25902604
token::CloseDelim(_) | token::Eof => unreachable!(),
25912605
_ => {
2592-
let token = mem::replace(&mut self.token, token::Underscore);
2606+
let (token, span) = (mem::replace(&mut self.token, token::Underscore), self.span);
25932607
self.bump();
2594-
TokenTree::Token(self.prev_span, token)
2608+
TokenTree::Token(span, token)
25952609
}
25962610
}
25972611
}
@@ -3489,9 +3503,9 @@ impl<'a> Parser<'a> {
34893503
fn parse_pat_ident(&mut self,
34903504
binding_mode: ast::BindingMode)
34913505
-> PResult<'a, PatKind> {
3506+
let ident_span = self.span;
34923507
let ident = self.parse_ident()?;
3493-
let prev_span = self.prev_span;
3494-
let name = codemap::Spanned{span: prev_span, node: ident};
3508+
let name = codemap::Spanned{span: ident_span, node: ident};
34953509
let sub = if self.eat(&token::At) {
34963510
Some(self.parse_pat()?)
34973511
} else {
@@ -4364,7 +4378,7 @@ impl<'a> Parser<'a> {
43644378
fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
43654379
let expect_ident = |this: &mut Self| match this.token {
43664380
// Preserve hygienic context.
4367-
token::Ident(ident) => { this.bump(); codemap::respan(this.prev_span, ident) }
4381+
token::Ident(ident) => { let sp = this.span; this.bump(); codemap::respan(sp, ident) }
43684382
_ => unreachable!()
43694383
};
43704384
let isolated_self = |this: &mut Self, n| {

src/libsyntax/parse/token.rs

+24-24
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,7 @@ impl Token {
211211
ModSep => true, // global path
212212
Pound => true, // expression attributes
213213
Interpolated(ref nt) => match **nt {
214-
NtExpr(..) => true,
215-
NtBlock(..) => true,
216-
NtPath(..) => true,
214+
NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true,
217215
_ => false,
218216
},
219217
_ => false,
@@ -236,8 +234,7 @@ impl Token {
236234
Lt | BinOp(Shl) => true, // associated path
237235
ModSep => true, // global path
238236
Interpolated(ref nt) => match **nt {
239-
NtTy(..) => true,
240-
NtPath(..) => true,
237+
NtIdent(..) | NtTy(..) | NtPath(..) => true,
241238
_ => false,
242239
},
243240
_ => false,
@@ -252,14 +249,22 @@ impl Token {
252249
}
253250
}
254251

255-
/// Returns `true` if the token is an identifier.
256-
pub fn is_ident(&self) -> bool {
252+
pub fn ident(&self) -> Option<ast::Ident> {
257253
match *self {
258-
Ident(..) => true,
259-
_ => false,
254+
Ident(ident) => Some(ident),
255+
Interpolated(ref nt) => match **nt {
256+
NtIdent(ident) => Some(ident.node),
257+
_ => None,
258+
},
259+
_ => None,
260260
}
261261
}
262262

263+
/// Returns `true` if the token is an identifier.
264+
pub fn is_ident(&self) -> bool {
265+
self.ident().is_some()
266+
}
267+
263268
/// Returns `true` if the token is a documentation comment.
264269
pub fn is_doc_comment(&self) -> bool {
265270
match *self {
@@ -311,18 +316,15 @@ impl Token {
311316

312317
/// Returns `true` if the token is a given keyword, `kw`.
313318
pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
314-
match *self {
315-
Ident(id) => id.name == kw.name(),
316-
_ => false,
317-
}
319+
self.ident().map(|ident| ident.name == kw.name()).unwrap_or(false)
318320
}
319321

320322
pub fn is_path_segment_keyword(&self) -> bool {
321-
match *self {
322-
Ident(id) => id.name == keywords::Super.name() ||
323-
id.name == keywords::SelfValue.name() ||
324-
id.name == keywords::SelfType.name(),
325-
_ => false,
323+
match self.ident() {
324+
Some(id) => id.name == keywords::Super.name() ||
325+
id.name == keywords::SelfValue.name() ||
326+
id.name == keywords::SelfType.name(),
327+
None => false,
326328
}
327329
}
328330

@@ -333,18 +335,16 @@ impl Token {
333335

334336
/// Returns `true` if the token is a strict keyword.
335337
pub fn is_strict_keyword(&self) -> bool {
336-
match *self {
337-
Ident(id) => id.name >= keywords::As.name() &&
338-
id.name <= keywords::While.name(),
338+
match self.ident() {
339+
Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(),
339340
_ => false,
340341
}
341342
}
342343

343344
/// Returns `true` if the token is a keyword reserved for possible future use.
344345
pub fn is_reserved_keyword(&self) -> bool {
345-
match *self {
346-
Ident(id) => id.name >= keywords::Abstract.name() &&
347-
id.name <= keywords::Yield.name(),
346+
match self.ident() {
347+
Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(),
348348
_ => false,
349349
}
350350
}

0 commit comments

Comments
 (0)