From f4a03c44d5859dea64dea7fdbaef5377f37c5dd2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 5 Mar 2020 00:34:57 +0300 Subject: [PATCH] rustc_ast: Introduce `Token::uninterpolated_span` --- src/librustc_ast/attr/mod.rs | 4 ++++ src/librustc_ast/token.rs | 30 ++++++++++++++++++++++++++++++ src/librustc_parse/parser/expr.rs | 17 ++++++++++------- src/librustc_parse/parser/item.rs | 2 +- src/librustc_parse/parser/mod.rs | 6 +++--- src/librustc_parse/parser/ty.rs | 2 +- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index 0638e8e6676..280994116c0 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -286,6 +286,10 @@ impl MetaItem { } impl AttrItem { + pub fn span(&self) -> Span { + self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span)) + } + pub fn meta(&self, span: Span) -> Option { Some(MetaItem { path: self.path.clone(), diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index a8a2c9b2fb3..c1564882cfe 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -328,6 +328,18 @@ impl Token { mem::replace(self, Token::dummy()) } + /// For interpolated tokens returns a span of the fragment to which the interpolated + /// token refers, for all other tokens this is just a regular span. + /// It is particularly important to use this for identifiers and lifetimes + /// for which spans affect name resolution. This also includes edition checks + /// for edition-specific keyword identifiers. + pub fn uninterpolated_span(&self) -> Span { + match &self.kind { + Interpolated(nt) => nt.span(), + _ => self.span, + } + } + pub fn is_op(&self) -> bool { match self.kind { OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..) @@ -714,6 +726,24 @@ pub enum Nonterminal { #[cfg(target_arch = "x86_64")] rustc_data_structures::static_assert_size!(Nonterminal, 40); +impl Nonterminal { + fn span(&self) -> Span { + match self { + NtItem(item) => item.span, + NtBlock(block) => block.span, + NtStmt(stmt) => stmt.span, + NtPat(pat) => pat.span, + NtExpr(expr) | NtLiteral(expr) => expr.span, + NtTy(ty) => ty.span, + NtIdent(ident, _) | NtLifetime(ident) => ident.span, + NtMeta(attr_item) => attr_item.span(), + NtPath(path) => path.span, + NtVis(vis) => vis.span, + NtTT(tt) => tt.span(), + } + } +} + impl PartialEq for Nonterminal { fn eq(&self, rhs: &Self) -> bool { match (self, rhs) { diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 66266aa5dc4..743fc3a4efa 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -849,7 +849,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.normalized_token.span.rust_2018() && self.eat_keyword(kw::Await) { + if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { return self.mk_await_expr(self_arg, lo); } @@ -963,7 +963,7 @@ impl<'a> Parser<'a> { // | ^ expected expression self.bump(); Ok(self.mk_expr_err(self.token.span)) - } else if self.normalized_token.span.rust_2018() { + } else if self.token.uninterpolated_span().rust_2018() { // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. if self.check_keyword(kw::Async) { if self.is_async_block() { @@ -1396,11 +1396,14 @@ impl<'a> Parser<'a> { let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; - let asyncness = - if self.normalized_token.span.rust_2018() { self.parse_asyncness() } else { Async::No }; - if asyncness.is_async() { + let asyncness = if self.token.uninterpolated_span().rust_2018() { + self.parse_asyncness() + } else { + Async::No + }; + if let Async::Yes { span, .. } = asyncness { // Feature-gate `async ||` closures. - self.sess.gated_spans.gate(sym::async_closure, self.normalized_prev_token.span); + self.sess.gated_spans.gate(sym::async_closure, span); } let capture_clause = self.parse_capture_clause(); @@ -1756,7 +1759,7 @@ impl<'a> Parser<'a> { fn is_try_block(&self) -> bool { self.token.is_keyword(kw::Try) && self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && - self.normalized_token.span.rust_2018() && + self.token.uninterpolated_span().rust_2018() && // Prevent `while try {} {}`, `if try {} {} else {}`, etc. !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index c1b38591f56..232ecd6fdae 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -574,7 +574,7 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As)) { self.bump(); // `default` - Defaultness::Default(self.normalized_prev_token.span) + Defaultness::Default(self.prev_token.uninterpolated_span()) } else { Defaultness::Final } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 0e3cee45dcd..252a80431ac 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -884,7 +884,7 @@ impl<'a> Parser<'a> { /// Parses asyncness: `async` or nothing. fn parse_asyncness(&mut self) -> Async { if self.eat_keyword(kw::Async) { - let span = self.normalized_prev_token.span; + let span = self.prev_token.uninterpolated_span(); Async::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID } } else { Async::No @@ -894,7 +894,7 @@ impl<'a> Parser<'a> { /// Parses unsafety: `unsafe` or nothing. fn parse_unsafety(&mut self) -> Unsafe { if self.eat_keyword(kw::Unsafe) { - Unsafe::Yes(self.normalized_prev_token.span) + Unsafe::Yes(self.prev_token.uninterpolated_span()) } else { Unsafe::No } @@ -903,7 +903,7 @@ impl<'a> Parser<'a> { /// Parses constness: `const` or nothing. fn parse_constness(&mut self) -> Const { if self.eat_keyword(kw::Const) { - Const::Yes(self.normalized_prev_token.span) + Const::Yes(self.prev_token.uninterpolated_span()) } else { Const::No } diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index c4469331b66..16adf5c05a4 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -323,7 +323,7 @@ impl<'a> Parser<'a> { /// Is a `dyn B0 + ... + Bn` type allowed here? fn is_explicit_dyn_type(&mut self) -> bool { self.check_keyword(kw::Dyn) - && (self.normalized_token.span.rust_2018() + && (self.token.uninterpolated_span().rust_2018() || self.look_ahead(1, |t| { t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t) }))