rustc_ast: Introduce Token::uninterpolated_span

This commit is contained in:
Vadim Petrochenkov 2020-03-05 00:34:57 +03:00
parent 925e9a2188
commit f4a03c44d5
6 changed files with 49 additions and 12 deletions

View File

@ -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<MetaItem> {
Some(MetaItem {
path: self.path.clone(),

View File

@ -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) {

View File

@ -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<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}))