More detail when expecting expression but encountering bad macro argument
Partially address #71039.
This commit is contained in:
parent
1be1e84872
commit
4e418805da
27 changed files with 200 additions and 67 deletions
|
@ -342,7 +342,7 @@ impl MetaItem {
|
|||
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
|
||||
Path { span, segments, tokens: None }
|
||||
}
|
||||
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt {
|
||||
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &nt.0 {
|
||||
token::Nonterminal::NtMeta(item) => return item.meta(item.path.span),
|
||||
token::Nonterminal::NtPath(path) => (**path).clone(),
|
||||
_ => return None,
|
||||
|
|
|
@ -764,7 +764,10 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
|||
return; // Avoid visiting the span for the second time.
|
||||
}
|
||||
token::Interpolated(nt) => {
|
||||
visit_nonterminal(Lrc::make_mut(nt), vis);
|
||||
let nt = Lrc::make_mut(nt);
|
||||
let (nt, sp) = (&mut nt.0, &mut nt.1);
|
||||
vis.visit_span(sp);
|
||||
visit_nonterminal(nt, vis);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ impl Lit {
|
|||
Ident(name, false) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
|
||||
Literal(token_lit) => Some(token_lit),
|
||||
Interpolated(ref nt)
|
||||
if let NtExpr(expr) | NtLiteral(expr) = &**nt
|
||||
if let NtExpr(expr) | NtLiteral(expr) = &nt.0
|
||||
&& let ast::ExprKind::Lit(token_lit) = expr.kind =>
|
||||
{
|
||||
Some(token_lit)
|
||||
|
@ -314,7 +314,7 @@ pub enum TokenKind {
|
|||
/// - It prevents `Token` from implementing `Copy`.
|
||||
/// It adds complexity and likely slows things down. Please don't add new
|
||||
/// occurrences of this token kind!
|
||||
Interpolated(Lrc<Nonterminal>),
|
||||
Interpolated(Lrc<(Nonterminal, Span)>),
|
||||
|
||||
/// A doc comment token.
|
||||
/// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
|
||||
|
@ -421,7 +421,7 @@ impl Token {
|
|||
/// if they keep spans or perform edition checks.
|
||||
pub fn uninterpolated_span(&self) -> Span {
|
||||
match &self.kind {
|
||||
Interpolated(nt) => nt.span(),
|
||||
Interpolated(nt) => nt.0.use_span(),
|
||||
_ => self.span,
|
||||
}
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ impl Token {
|
|||
ModSep | // global path
|
||||
Lifetime(..) | // labeled loop
|
||||
Pound => true, // expression attributes
|
||||
Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
|
||||
Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
|
||||
NtExpr(..) |
|
||||
NtBlock(..) |
|
||||
NtPath(..)),
|
||||
|
@ -488,7 +488,7 @@ impl Token {
|
|||
| DotDot | DotDotDot | DotDotEq // ranges
|
||||
| Lt | BinOp(Shl) // associated path
|
||||
| ModSep => true, // global path
|
||||
Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
|
||||
Interpolated(ref nt) => matches!(&nt.0, NtLiteral(..) |
|
||||
NtPat(..) |
|
||||
NtBlock(..) |
|
||||
NtPath(..)),
|
||||
|
@ -511,7 +511,7 @@ impl Token {
|
|||
Lifetime(..) | // lifetime bound in trait object
|
||||
Lt | BinOp(Shl) | // associated path
|
||||
ModSep => true, // global path
|
||||
Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
|
||||
Interpolated(ref nt) => matches!(&nt.0, NtTy(..) | NtPath(..)),
|
||||
// For anonymous structs or unions, which only appear in specific positions
|
||||
// (type of struct fields or union fields), we don't consider them as regular types
|
||||
_ => false,
|
||||
|
@ -522,7 +522,7 @@ impl Token {
|
|||
pub fn can_begin_const_arg(&self) -> bool {
|
||||
match self.kind {
|
||||
OpenDelim(Delimiter::Brace) => true,
|
||||
Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
|
||||
Interpolated(ref nt) => matches!(&nt.0, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
|
||||
_ => self.can_begin_literal_maybe_minus(),
|
||||
}
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ impl Token {
|
|||
match self.uninterpolate().kind {
|
||||
Literal(..) | BinOp(Minus) => true,
|
||||
Ident(name, false) if name.is_bool_lit() => true,
|
||||
Interpolated(ref nt) => match &**nt {
|
||||
Interpolated(ref nt) => match &nt.0 {
|
||||
NtLiteral(_) => true,
|
||||
NtExpr(e) => match &e.kind {
|
||||
ast::ExprKind::Lit(_) => true,
|
||||
|
@ -597,9 +597,9 @@ impl Token {
|
|||
/// otherwise returns the original token.
|
||||
pub fn uninterpolate(&self) -> Cow<'_, Token> {
|
||||
match &self.kind {
|
||||
Interpolated(nt) => match **nt {
|
||||
Interpolated(nt) => match &nt.0 {
|
||||
NtIdent(ident, is_raw) => {
|
||||
Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
|
||||
Cow::Owned(Token::new(Ident(ident.name, *is_raw), ident.span))
|
||||
}
|
||||
NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
|
||||
_ => Cow::Borrowed(self),
|
||||
|
@ -614,8 +614,8 @@ impl Token {
|
|||
// We avoid using `Token::uninterpolate` here because it's slow.
|
||||
match &self.kind {
|
||||
&Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
|
||||
Interpolated(nt) => match **nt {
|
||||
NtIdent(ident, is_raw) => Some((ident, is_raw)),
|
||||
Interpolated(nt) => match &nt.0 {
|
||||
NtIdent(ident, is_raw) => Some((*ident, *is_raw)),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
@ -628,8 +628,8 @@ impl Token {
|
|||
// We avoid using `Token::uninterpolate` here because it's slow.
|
||||
match &self.kind {
|
||||
&Lifetime(name) => Some(Ident::new(name, self.span)),
|
||||
Interpolated(nt) => match **nt {
|
||||
NtLifetime(ident) => Some(ident),
|
||||
Interpolated(nt) => match &nt.0 {
|
||||
NtLifetime(ident) => Some(*ident),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
@ -655,7 +655,7 @@ impl Token {
|
|||
/// Returns `true` if the token is an interpolated path.
|
||||
fn is_path(&self) -> bool {
|
||||
if let Interpolated(nt) = &self.kind
|
||||
&& let NtPath(..) = **nt
|
||||
&& let NtPath(..) = &nt.0
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -668,7 +668,7 @@ impl Token {
|
|||
/// (which happens while parsing the result of macro expansion)?
|
||||
pub fn is_whole_expr(&self) -> bool {
|
||||
if let Interpolated(nt) = &self.kind
|
||||
&& let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt
|
||||
&& let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = &nt.0
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -679,7 +679,7 @@ impl Token {
|
|||
/// Is the token an interpolated block (`$b:block`)?
|
||||
pub fn is_whole_block(&self) -> bool {
|
||||
if let Interpolated(nt) = &self.kind
|
||||
&& let NtBlock(..) = **nt
|
||||
&& let NtBlock(..) = &nt.0
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -927,7 +927,7 @@ impl fmt::Display for NonterminalKind {
|
|||
}
|
||||
|
||||
impl Nonterminal {
|
||||
pub fn span(&self) -> Span {
|
||||
pub fn use_span(&self) -> Span {
|
||||
match self {
|
||||
NtItem(item) => item.span,
|
||||
NtBlock(block) => block.span,
|
||||
|
@ -941,6 +941,23 @@ impl Nonterminal {
|
|||
NtVis(vis) => vis.span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
NtItem(..) => "item",
|
||||
NtBlock(..) => "block",
|
||||
NtStmt(..) => "statement",
|
||||
NtPat(..) => "pattern",
|
||||
NtExpr(..) => "expression",
|
||||
NtLiteral(..) => "literal",
|
||||
NtTy(..) => "type",
|
||||
NtIdent(..) => "identifier",
|
||||
NtLifetime(..) => "lifetime",
|
||||
NtMeta(..) => "attribute",
|
||||
NtPath(..) => "path",
|
||||
NtVis(..) => "visibility",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Nonterminal {
|
||||
|
|
|
@ -477,13 +477,13 @@ impl TokenStream {
|
|||
|
||||
fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
|
||||
match &token.kind {
|
||||
token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = **nt => {
|
||||
token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = nt.0 => {
|
||||
TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
|
||||
}
|
||||
token::Interpolated(nt) => TokenTree::Delimited(
|
||||
DelimSpan::from_single(token.span),
|
||||
Delimiter::Invisible,
|
||||
TokenStream::from_nonterminal_ast(nt).flattened(),
|
||||
TokenStream::from_nonterminal_ast(&nt.0).flattened(),
|
||||
),
|
||||
_ => TokenTree::Token(token.clone(), spacing),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue