1
Fork 0

Attach TokenStream to ast::Visibility

A `Visibility` does not have outer attributes, so we only capture tokens
when parsing a `macro_rules!` matcher
This commit is contained in:
Aaron Hill 2020-08-21 19:11:00 -04:00
parent 55082ce413
commit c1011165e6
No known key found for this signature in database
GPG key ID: B4087E510E98B164
22 changed files with 120 additions and 50 deletions

View file

@ -279,6 +279,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
}
Nonterminal::NtMeta(ref attr) => attr.tokens.clone(),
Nonterminal::NtPath(ref path) => path.tokens.clone(),
Nonterminal::NtVis(ref vis) => vis.tokens.clone(),
Nonterminal::NtTT(ref tt) => Some(tt.clone().into()),
Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => {
if expr.tokens.is_none() {
@ -286,7 +287,6 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
}
prepend_attrs(sess, &expr.attrs, expr.tokens.as_ref(), span)
}
_ => None,
};
// FIXME(#43081): Avoid this pretty-print + reparse hack

View file

@ -187,7 +187,7 @@ impl<'a> Parser<'a> {
/// Error in-case a non-inherited visibility was parsed but no item followed.
fn error_on_unmatched_vis(&self, vis: &Visibility) {
if let VisibilityKind::Inherited = vis.node {
if let VisibilityKind::Inherited = vis.kind {
return;
}
let vs = pprust::vis_to_string(&vis);
@ -296,7 +296,7 @@ impl<'a> Parser<'a> {
} else if self.is_macro_rules_item() {
// MACRO_RULES ITEM
self.parse_item_macro_rules(vis)?
} else if vis.node.is_pub() && self.isnt_macro_invocation() {
} else if vis.kind.is_pub() && self.isnt_macro_invocation() {
self.recover_missing_kw_before_item()?;
return Ok(None);
} else if macros_allowed && self.check_path() {
@ -1418,7 +1418,7 @@ impl<'a> Parser<'a> {
/// Item macro invocations or `macro_rules!` definitions need inherited visibility.
/// If that's not the case, emit an error.
fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) {
if let VisibilityKind::Inherited = vis.node {
if let VisibilityKind::Inherited = vis.kind {
return;
}

View file

@ -22,7 +22,7 @@ use rustc_ast::{Async, MacArgs, MacDelimiter, Mutability, StrLit, Visibility, Vi
use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{respan, Span, DUMMY_SP};
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use tracing::debug;
@ -1022,14 +1022,22 @@ impl<'a> Parser<'a> {
if self.is_crate_vis() {
self.bump(); // `crate`
self.sess.gated_spans.gate(sym::crate_visibility_modifier, self.prev_token.span);
return Ok(respan(self.prev_token.span, VisibilityKind::Crate(CrateSugar::JustCrate)));
return Ok(Visibility {
span: self.prev_token.span,
kind: VisibilityKind::Crate(CrateSugar::JustCrate),
tokens: None,
});
}
if !self.eat_keyword(kw::Pub) {
// We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
// keyword to grab a span from for inherited visibility; an empty span at the
// beginning of the current token would seem to be the "Schelling span".
return Ok(respan(self.token.span.shrink_to_lo(), VisibilityKind::Inherited));
return Ok(Visibility {
span: self.token.span.shrink_to_lo(),
kind: VisibilityKind::Inherited,
tokens: None,
});
}
let lo = self.prev_token.span;
@ -1046,7 +1054,11 @@ impl<'a> Parser<'a> {
self.bump(); // `crate`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = VisibilityKind::Crate(CrateSugar::PubCrate);
return Ok(respan(lo.to(self.prev_token.span), vis));
return Ok(Visibility {
span: lo.to(self.prev_token.span),
kind: vis,
tokens: None,
});
} else if self.is_keyword_ahead(1, &[kw::In]) {
// Parse `pub(in path)`.
self.bump(); // `(`
@ -1054,7 +1066,11 @@ impl<'a> Parser<'a> {
let path = self.parse_path(PathStyle::Mod)?; // `path`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = VisibilityKind::Restricted { path: P(path), id: ast::DUMMY_NODE_ID };
return Ok(respan(lo.to(self.prev_token.span), vis));
return Ok(Visibility {
span: lo.to(self.prev_token.span),
kind: vis,
tokens: None,
});
} else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren))
&& self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
{
@ -1063,7 +1079,11 @@ impl<'a> Parser<'a> {
let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = VisibilityKind::Restricted { path: P(path), id: ast::DUMMY_NODE_ID };
return Ok(respan(lo.to(self.prev_token.span), vis));
return Ok(Visibility {
span: lo.to(self.prev_token.span),
kind: vis,
tokens: None,
});
} else if let FollowedByType::No = fbt {
// Provide this diagnostic if a type cannot follow;
// in particular, if this is not a tuple struct.
@ -1072,7 +1092,7 @@ impl<'a> Parser<'a> {
}
}
Ok(respan(lo, VisibilityKind::Public))
Ok(Visibility { span: lo, kind: VisibilityKind::Public, tokens: None })
}
/// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`

View file

@ -186,7 +186,15 @@ impl<'a> Parser<'a> {
token::NtMeta(P(attr))
}
NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
NonterminalKind::Vis => token::NtVis(self.parse_visibility(FollowedByType::Yes)?),
NonterminalKind::Vis => {
let (mut vis, tokens) =
self.collect_tokens(|this| this.parse_visibility(FollowedByType::Yes))?;
// We may have etan an `NtVis`, which could already have tokens
if vis.tokens.is_none() {
vis.tokens = Some(tokens);
}
token::NtVis(vis)
}
NonterminalKind::Lifetime => {
if self.check_lifetime() {
token::NtLifetime(self.expect_lifetime().ident)