syntax: Introduce a struct MacArgs
for macro arguments
This commit is contained in:
parent
fdc0011561
commit
a81804b4d5
19 changed files with 192 additions and 112 deletions
|
@ -1453,7 +1453,7 @@ impl EarlyLintPass for KeywordIdents {
|
||||||
self.check_tokens(cx, mac_def.stream());
|
self.check_tokens(cx, mac_def.stream());
|
||||||
}
|
}
|
||||||
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
|
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) {
|
||||||
self.check_tokens(cx, mac.tts.clone().into());
|
self.check_tokens(cx, mac.args.inner_tokens());
|
||||||
}
|
}
|
||||||
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
|
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) {
|
||||||
self.check_ident_token(cx, UnderMacro(false), ident);
|
self.check_ident_token(cx, UnderMacro(false), ident);
|
||||||
|
|
|
@ -244,7 +244,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(attrs)
|
Ok(attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
|
pub(super) fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
|
||||||
let lit = self.parse_lit()?;
|
let lit = self.parse_lit()?;
|
||||||
debug!("checking if {:?} is unusuffixed", lit);
|
debug!("checking if {:?} is unusuffixed", lit);
|
||||||
|
|
||||||
|
|
|
@ -922,12 +922,11 @@ impl<'a> Parser<'a> {
|
||||||
// `!`, as an operator, is prefix, so we know this isn't that.
|
// `!`, as an operator, is prefix, so we know this isn't that.
|
||||||
if self.eat(&token::Not) {
|
if self.eat(&token::Not) {
|
||||||
// MACRO INVOCATION expression
|
// MACRO INVOCATION expression
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
hi = self.prev_span;
|
hi = self.prev_span;
|
||||||
ex = ExprKind::Mac(Mac {
|
ex = ExprKind::Mac(Mac {
|
||||||
path,
|
path,
|
||||||
tts,
|
args,
|
||||||
delim,
|
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
prior_type_ascription: self.last_type_ascription,
|
prior_type_ascription: self.last_type_ascription,
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, Us
|
||||||
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
|
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
|
||||||
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
||||||
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
|
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
|
||||||
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
use syntax::ast::{Mac, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::ThinVec;
|
use syntax::ThinVec;
|
||||||
|
@ -437,16 +437,15 @@ impl<'a> Parser<'a> {
|
||||||
// Item macro
|
// Item macro
|
||||||
let path = self.parse_path(PathStyle::Mod)?;
|
let path = self.parse_path(PathStyle::Mod)?;
|
||||||
self.expect(&token::Not)?;
|
self.expect(&token::Not)?;
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
|
if args.need_semicolon() && !self.eat(&token::Semi) {
|
||||||
self.report_invalid_macro_expansion_item();
|
self.report_invalid_macro_expansion_item();
|
||||||
}
|
}
|
||||||
|
|
||||||
let hi = self.prev_span;
|
let hi = self.prev_span;
|
||||||
let mac = Mac {
|
let mac = Mac {
|
||||||
path,
|
path,
|
||||||
tts,
|
args,
|
||||||
delim,
|
|
||||||
span: mac_lo.to(hi),
|
span: mac_lo.to(hi),
|
||||||
prior_type_ascription: self.last_type_ascription,
|
prior_type_ascription: self.last_type_ascription,
|
||||||
};
|
};
|
||||||
|
@ -518,15 +517,14 @@ impl<'a> Parser<'a> {
|
||||||
*at_end = true;
|
*at_end = true;
|
||||||
|
|
||||||
// eat a matched-delimiter token tree:
|
// eat a matched-delimiter token tree:
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
if delim != MacDelimiter::Brace {
|
if args.need_semicolon() {
|
||||||
self.expect_semi()?;
|
self.expect_semi()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(Mac {
|
Ok(Some(Mac {
|
||||||
path,
|
path,
|
||||||
tts,
|
args,
|
||||||
delim,
|
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
prior_type_ascription: self.last_type_ascription,
|
prior_type_ascription: self.last_type_ascription,
|
||||||
}))
|
}))
|
||||||
|
@ -1660,12 +1658,12 @@ impl<'a> Parser<'a> {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
let (delim, tokens) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
|
if args.need_semicolon() && !self.eat(&token::Semi) {
|
||||||
self.report_invalid_macro_expansion_item();
|
self.report_invalid_macro_expansion_item();
|
||||||
}
|
}
|
||||||
|
|
||||||
(ident, ast::MacroDef { tokens, legacy: true })
|
(ident, ast::MacroDef { tokens: args.inner_tokens(), legacy: true })
|
||||||
} else {
|
} else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::lexer::UnmatchedBrace;
|
||||||
|
|
||||||
use syntax::ast::{
|
use syntax::ast::{
|
||||||
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
|
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
|
||||||
IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
|
IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
|
||||||
};
|
};
|
||||||
|
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
|
@ -1010,27 +1010,49 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
|
fn parse_mac_args(&mut self) -> PResult<'a, P<MacArgs>> {
|
||||||
let delim = match self.token.kind {
|
self.parse_mac_args_common(true)
|
||||||
token::OpenDelim(delim) => delim,
|
|
||||||
_ => {
|
|
||||||
let msg = "expected open delimiter";
|
|
||||||
let mut err = self.fatal(msg);
|
|
||||||
err.span_label(self.token.span, msg);
|
|
||||||
return Err(err)
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
let tts = match self.parse_token_tree() {
|
#[allow(dead_code)]
|
||||||
TokenTree::Delimited(_, _, tts) => tts,
|
fn parse_attr_args(&mut self) -> PResult<'a, P<MacArgs>> {
|
||||||
|
self.parse_mac_args_common(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_mac_args_common(&mut self, delimited_only: bool) -> PResult<'a, P<MacArgs>> {
|
||||||
|
Ok(P(if self.check(&token::OpenDelim(DelimToken::Paren)) ||
|
||||||
|
self.check(&token::OpenDelim(DelimToken::Bracket)) ||
|
||||||
|
self.check(&token::OpenDelim(DelimToken::Brace)) {
|
||||||
|
match self.parse_token_tree() {
|
||||||
|
TokenTree::Delimited(dspan, delim, tokens) =>
|
||||||
|
MacArgs::Delimited(dspan, MacDelimiter::from_token(delim), tokens),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
} else if !delimited_only {
|
||||||
|
if self.eat(&token::Eq) {
|
||||||
|
let eq_span = self.prev_span;
|
||||||
|
let mut is_interpolated_expr = false;
|
||||||
|
if let token::Interpolated(nt) = &self.token.kind {
|
||||||
|
if let token::NtExpr(..) = **nt {
|
||||||
|
is_interpolated_expr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let token_tree = if is_interpolated_expr {
|
||||||
|
// We need to accept arbitrary interpolated expressions to continue
|
||||||
|
// supporting things like `doc = $expr` that work on stable.
|
||||||
|
// Non-literal interpolated expressions are rejected after expansion.
|
||||||
|
self.parse_token_tree()
|
||||||
|
} else {
|
||||||
|
self.parse_unsuffixed_lit()?.token_tree()
|
||||||
};
|
};
|
||||||
let delim = match delim {
|
|
||||||
token::Paren => MacDelimiter::Parenthesis,
|
MacArgs::Eq(eq_span, token_tree.into())
|
||||||
token::Bracket => MacDelimiter::Bracket,
|
} else {
|
||||||
token::Brace => MacDelimiter::Brace,
|
MacArgs::Empty
|
||||||
token::NoDelim => self.bug("unexpected no delimiter"),
|
}
|
||||||
};
|
} else {
|
||||||
Ok((delim, tts.into()))
|
return self.unexpected();
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_or_use_outer_attributes(
|
fn parse_or_use_outer_attributes(
|
||||||
|
|
|
@ -595,11 +595,10 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse macro invocation
|
/// Parse macro invocation
|
||||||
fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> {
|
fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> {
|
||||||
self.bump();
|
self.bump();
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
let mac = Mac {
|
let mac = Mac {
|
||||||
path,
|
path,
|
||||||
tts,
|
args,
|
||||||
delim,
|
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
prior_type_ascription: self.last_type_ascription,
|
prior_type_ascription: self.last_type_ascription,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ use syntax::ThinVec;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast::{DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
|
use syntax::ast::{DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
|
||||||
use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter};
|
use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac};
|
||||||
use syntax::util::classify;
|
use syntax::util::classify;
|
||||||
use syntax::token;
|
use syntax::token;
|
||||||
use syntax::source_map::{respan, Span};
|
use syntax::source_map::{respan, Span};
|
||||||
|
@ -93,10 +93,11 @@ impl<'a> Parser<'a> {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
|
let delim = args.delim();
|
||||||
let hi = self.prev_span;
|
let hi = self.prev_span;
|
||||||
|
|
||||||
let style = if delim == MacDelimiter::Brace {
|
let style = if delim == token::Brace {
|
||||||
MacStmtStyle::Braces
|
MacStmtStyle::Braces
|
||||||
} else {
|
} else {
|
||||||
MacStmtStyle::NoBraces
|
MacStmtStyle::NoBraces
|
||||||
|
@ -104,12 +105,11 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let mac = Mac {
|
let mac = Mac {
|
||||||
path,
|
path,
|
||||||
tts,
|
args,
|
||||||
delim,
|
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
prior_type_ascription: self.last_type_ascription,
|
prior_type_ascription: self.last_type_ascription,
|
||||||
};
|
};
|
||||||
let kind = if delim == MacDelimiter::Brace ||
|
let kind = if delim == token::Brace ||
|
||||||
self.token == token::Semi || self.token == token::Eof {
|
self.token == token::Semi || self.token == token::Eof {
|
||||||
StmtKind::Mac(P((mac, style, attrs.into())))
|
StmtKind::Mac(P((mac, style, attrs.into())))
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,11 +177,10 @@ impl<'a> Parser<'a> {
|
||||||
let path = self.parse_path(PathStyle::Type)?;
|
let path = self.parse_path(PathStyle::Type)?;
|
||||||
if self.eat(&token::Not) {
|
if self.eat(&token::Not) {
|
||||||
// Macro invocation in type position
|
// Macro invocation in type position
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let args = self.parse_mac_args()?;
|
||||||
let mac = Mac {
|
let mac = Mac {
|
||||||
path,
|
path,
|
||||||
tts,
|
args,
|
||||||
delim,
|
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
prior_type_ascription: self.last_type_ascription,
|
prior_type_ascription: self.last_type_ascription,
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub use syntax_pos::symbol::{Ident, Symbol as Name};
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::source_map::{dummy_spanned, respan, Spanned};
|
use crate::source_map::{dummy_spanned, respan, Spanned};
|
||||||
use crate::token::{self, DelimToken};
|
use crate::token::{self, DelimToken};
|
||||||
use crate::tokenstream::TokenStream;
|
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
|
||||||
|
|
||||||
use syntax_pos::symbol::{kw, sym, Symbol};
|
use syntax_pos::symbol::{kw, sym, Symbol};
|
||||||
use syntax_pos::{Span, DUMMY_SP, ExpnId};
|
use syntax_pos::{Span, DUMMY_SP, ExpnId};
|
||||||
|
@ -40,6 +40,7 @@ use rustc_index::vec::Idx;
|
||||||
use rustc_serialize::{self, Decoder, Encoder};
|
use rustc_serialize::{self, Decoder, Encoder};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
|
|
||||||
|
use std::iter;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1372,21 +1373,71 @@ pub enum Movability {
|
||||||
Movable,
|
Movable,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a macro invocation. The `Path` indicates which macro
|
/// Represents a macro invocation. The `path` indicates which macro
|
||||||
/// is being invoked, and the vector of token-trees contains the source
|
/// is being invoked, and the `args` are arguments passed to it.
|
||||||
/// of the macro invocation.
|
|
||||||
///
|
|
||||||
/// N.B., the additional ident for a `macro_rules`-style macro is actually
|
|
||||||
/// stored in the enclosing item.
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct Mac {
|
pub struct Mac {
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
pub delim: MacDelimiter,
|
pub args: P<MacArgs>,
|
||||||
pub tts: TokenStream,
|
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub prior_type_ascription: Option<(Span, bool)>,
|
pub prior_type_ascription: Option<(Span, bool)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Arguments passed to an attribute or a function-like macro.
|
||||||
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
pub enum MacArgs {
|
||||||
|
/// No arguments - `#[attr]`.
|
||||||
|
Empty,
|
||||||
|
/// Delimited arguments - `#[attr()/[]/{}]` or `mac!()/[]/{}`.
|
||||||
|
Delimited(DelimSpan, MacDelimiter, TokenStream),
|
||||||
|
/// Arguments of a key-value attribute - `#[attr = "value"]`.
|
||||||
|
/// Span belongs to the `=` token, token stream is the "value".
|
||||||
|
Eq(Span, TokenStream),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MacArgs {
|
||||||
|
pub fn delim(&self) -> DelimToken {
|
||||||
|
match self {
|
||||||
|
MacArgs::Delimited(_, delim, _) => delim.to_token(),
|
||||||
|
MacArgs::Empty | MacArgs::Eq(..) => token::NoDelim,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tokens inside the delimiters or after `=`.
|
||||||
|
/// Proc macros see these tokens, for example.
|
||||||
|
pub fn inner_tokens(&self) -> TokenStream {
|
||||||
|
match self {
|
||||||
|
MacArgs::Empty => TokenStream::default(),
|
||||||
|
MacArgs::Delimited(.., tokens) => tokens.clone(),
|
||||||
|
MacArgs::Eq(.., tokens) => tokens.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tokens together with the delimiters or `=`.
|
||||||
|
/// Use of this functions generally means that something suspicious or hacky is happening.
|
||||||
|
pub fn outer_tokens(&self) -> TokenStream {
|
||||||
|
match *self {
|
||||||
|
MacArgs::Empty => TokenStream::default(),
|
||||||
|
MacArgs::Delimited(dspan, delim, ref tokens) =>
|
||||||
|
TokenTree::Delimited(dspan, delim.to_token(), tokens.clone()).into(),
|
||||||
|
MacArgs::Eq(eq_span, ref tokens) => iter::once(TokenTree::token(token::Eq, eq_span))
|
||||||
|
.chain(tokens.trees()).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether a macro with these arguments needs a semicolon
|
||||||
|
/// when used as a standalone item or statement.
|
||||||
|
pub fn need_semicolon(&self) -> bool {
|
||||||
|
!matches!(self, MacArgs::Delimited(_, MacDelimiter::Brace ,_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mac {
|
||||||
|
pub fn stream(&self) -> TokenStream {
|
||||||
|
self.args.inner_tokens()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum MacDelimiter {
|
pub enum MacDelimiter {
|
||||||
Parenthesis,
|
Parenthesis,
|
||||||
|
@ -1394,12 +1445,6 @@ pub enum MacDelimiter {
|
||||||
Brace,
|
Brace,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mac {
|
|
||||||
pub fn stream(&self) -> TokenStream {
|
|
||||||
self.tts.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MacDelimiter {
|
impl MacDelimiter {
|
||||||
crate fn to_token(self) -> DelimToken {
|
crate fn to_token(self) -> DelimToken {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1408,6 +1453,15 @@ impl MacDelimiter {
|
||||||
MacDelimiter::Brace => DelimToken::Brace,
|
MacDelimiter::Brace => DelimToken::Brace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_token(delim: DelimToken) -> MacDelimiter {
|
||||||
|
match delim {
|
||||||
|
token::Paren => MacDelimiter::Parenthesis,
|
||||||
|
token::Bracket => MacDelimiter::Bracket,
|
||||||
|
token::Brace => MacDelimiter::Brace,
|
||||||
|
token::NoDelim => panic!("expected a delimiter"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a macro definition.
|
/// Represents a macro definition.
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#![feature(const_transmute)]
|
#![feature(const_transmute)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(label_break_value)]
|
#![feature(label_break_value)]
|
||||||
|
#![feature(matches_macro)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(try_trait)]
|
#![feature(try_trait)]
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
|
|
|
@ -359,6 +359,26 @@ pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl }: &mut FnSig, vis: &mut
|
||||||
vis.visit_fn_decl(decl);
|
vis.visit_fn_decl(decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||||
|
pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
|
||||||
|
match args {
|
||||||
|
MacArgs::Empty => {}
|
||||||
|
MacArgs::Delimited(dspan, _delim, tokens) => {
|
||||||
|
visit_delim_span(dspan, vis);
|
||||||
|
vis.visit_tts(tokens);
|
||||||
|
}
|
||||||
|
MacArgs::Eq(eq_span, tokens) => {
|
||||||
|
vis.visit_span(eq_span);
|
||||||
|
vis.visit_tts(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) {
|
||||||
|
vis.visit_span(&mut dspan.open);
|
||||||
|
vis.visit_span(&mut dspan.close);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noop_flat_map_field_pattern<T: MutVisitor>(
|
pub fn noop_flat_map_field_pattern<T: MutVisitor>(
|
||||||
mut fp: FieldPat,
|
mut fp: FieldPat,
|
||||||
vis: &mut T,
|
vis: &mut T,
|
||||||
|
@ -560,9 +580,9 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) {
|
pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) {
|
||||||
let Mac { path, delim: _, tts, span, prior_type_ascription: _ } = mac;
|
let Mac { path, args, span, prior_type_ascription: _ } = mac;
|
||||||
vis.visit_path(path);
|
vis.visit_path(path);
|
||||||
vis.visit_tts(tts);
|
visit_mac_args(args, vis);
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
use crate::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||||
use crate::ast::{SelfKind, GenericBound, TraitBoundModifier};
|
use crate::ast::{SelfKind, GenericBound, TraitBoundModifier};
|
||||||
use crate::ast::{Attribute, MacDelimiter, GenericArg};
|
use crate::ast::{Attribute, GenericArg};
|
||||||
use crate::util::parser::{self, AssocOp, Fixity};
|
use crate::util::parser::{self, AssocOp, Fixity};
|
||||||
use crate::util::comments;
|
use crate::util::comments;
|
||||||
use crate::attr;
|
use crate::attr;
|
||||||
|
@ -1097,9 +1097,8 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::Macro(ref m) => {
|
ast::ForeignItemKind::Macro(ref m) => {
|
||||||
self.print_mac(m);
|
self.print_mac(m);
|
||||||
match m.delim {
|
if m.args.need_semicolon() {
|
||||||
MacDelimiter::Brace => {},
|
self.s.word(";");
|
||||||
_ => self.s.word(";")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1361,9 +1360,8 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ItemKind::Mac(ref mac) => {
|
ast::ItemKind::Mac(ref mac) => {
|
||||||
self.print_mac(mac);
|
self.print_mac(mac);
|
||||||
match mac.delim {
|
if mac.args.need_semicolon() {
|
||||||
MacDelimiter::Brace => {}
|
self.s.word(";");
|
||||||
_ => self.s.word(";"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ItemKind::MacroDef(ref macro_def) => {
|
ast::ItemKind::MacroDef(ref macro_def) => {
|
||||||
|
@ -1578,9 +1576,8 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::TraitItemKind::Macro(ref mac) => {
|
ast::TraitItemKind::Macro(ref mac) => {
|
||||||
self.print_mac(mac);
|
self.print_mac(mac);
|
||||||
match mac.delim {
|
if mac.args.need_semicolon() {
|
||||||
MacDelimiter::Brace => {}
|
self.s.word(";");
|
||||||
_ => self.s.word(";"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1608,9 +1605,8 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ImplItemKind::Macro(ref mac) => {
|
ast::ImplItemKind::Macro(ref mac) => {
|
||||||
self.print_mac(mac);
|
self.print_mac(mac);
|
||||||
match mac.delim {
|
if mac.args.need_semicolon() {
|
||||||
MacDelimiter::Brace => {}
|
self.s.word(";");
|
||||||
_ => self.s.word(";"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1775,7 +1771,7 @@ impl<'a> State<'a> {
|
||||||
Some(MacHeader::Path(&m.path)),
|
Some(MacHeader::Path(&m.path)),
|
||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
m.delim.to_token(),
|
m.args.delim(),
|
||||||
m.stream(),
|
m.stream(),
|
||||||
true,
|
true,
|
||||||
m.span,
|
m.span,
|
||||||
|
|
|
@ -30,13 +30,6 @@ impl MutVisitor for Marker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Marker {
|
|
||||||
fn visit_delim_span(&mut self, dspan: &mut DelimSpan) {
|
|
||||||
self.visit_span(&mut dspan.open);
|
|
||||||
self.visit_span(&mut dspan.close);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
|
/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
|
||||||
enum Frame {
|
enum Frame {
|
||||||
Delimited { forest: Lrc<mbe::Delimited>, idx: usize, span: DelimSpan },
|
Delimited { forest: Lrc<mbe::Delimited>, idx: usize, span: DelimSpan },
|
||||||
|
@ -271,7 +264,7 @@ pub(super) fn transcribe(
|
||||||
// jump back out of the Delimited, pop the result_stack and add the new results back to
|
// jump back out of the Delimited, pop the result_stack and add the new results back to
|
||||||
// the previous results (from outside the Delimited).
|
// the previous results (from outside the Delimited).
|
||||||
mbe::TokenTree::Delimited(mut span, delimited) => {
|
mbe::TokenTree::Delimited(mut span, delimited) => {
|
||||||
marker.visit_delim_span(&mut span);
|
mut_visit::visit_delim_span(&mut span, &mut marker);
|
||||||
stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
|
stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
|
||||||
result_stack.push(mem::take(&mut result));
|
result_stack.push(mem::take(&mut result));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::expand::{AstFragment, AstFragmentKind};
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::source_map::{DUMMY_SP, dummy_spanned};
|
use syntax::source_map::{DUMMY_SP, dummy_spanned};
|
||||||
use syntax::tokenstream::TokenStream;
|
|
||||||
use syntax::mut_visit::*;
|
use syntax::mut_visit::*;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::ThinVec;
|
use syntax::ThinVec;
|
||||||
|
@ -17,8 +16,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
|
||||||
fn mac_placeholder() -> ast::Mac {
|
fn mac_placeholder() -> ast::Mac {
|
||||||
ast::Mac {
|
ast::Mac {
|
||||||
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
|
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
|
||||||
tts: TokenStream::default().into(),
|
args: P(ast::MacArgs::Empty),
|
||||||
delim: ast::MacDelimiter::Brace,
|
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
prior_type_ascription: None,
|
prior_type_ascription: None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use syntax::token::{self, TokenKind};
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::symbol::{sym, Symbol};
|
use syntax::symbol::{sym, Symbol};
|
||||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||||
use syntax_expand::base::*;
|
use syntax_expand::base::*;
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
|
|
||||||
|
@ -26,9 +26,7 @@ pub fn expand_assert<'cx>(
|
||||||
// `core::panic` and `std::panic` are different macros, so we use call-site
|
// `core::panic` and `std::panic` are different macros, so we use call-site
|
||||||
// context to pick up whichever is currently in scope.
|
// context to pick up whichever is currently in scope.
|
||||||
let sp = cx.with_call_site_ctxt(sp);
|
let sp = cx.with_call_site_ctxt(sp);
|
||||||
let panic_call = Mac {
|
let tokens = custom_message.unwrap_or_else(|| {
|
||||||
path: Path::from_ident(Ident::new(sym::panic, sp)),
|
|
||||||
tts: custom_message.unwrap_or_else(|| {
|
|
||||||
TokenStream::from(TokenTree::token(
|
TokenStream::from(TokenTree::token(
|
||||||
TokenKind::lit(token::Str, Symbol::intern(&format!(
|
TokenKind::lit(token::Str, Symbol::intern(&format!(
|
||||||
"assertion failed: {}",
|
"assertion failed: {}",
|
||||||
|
@ -36,8 +34,11 @@ pub fn expand_assert<'cx>(
|
||||||
)), None),
|
)), None),
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
))
|
))
|
||||||
}).into(),
|
});
|
||||||
delim: MacDelimiter::Parenthesis,
|
let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens));
|
||||||
|
let panic_call = Mac {
|
||||||
|
path: Path::from_ident(Ident::new(sym::panic, sp)),
|
||||||
|
args,
|
||||||
span: sp,
|
span: sp,
|
||||||
prior_type_ascription: None,
|
prior_type_ascription: None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,9 +11,9 @@ macro_rules! foo{
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
foo!();
|
foo!();
|
||||||
|
|
||||||
assert!({one! two()}); //~ ERROR expected open delimiter
|
assert!({one! two()}); //~ ERROR expected one of `(`, `[`, or `{`, found `two`
|
||||||
|
|
||||||
// regardless of whether nested macro_rules works, the following should at
|
// regardless of whether nested macro_rules works, the following should at
|
||||||
// least throw a conventional error.
|
// least throw a conventional error.
|
||||||
assert!({one! two}); //~ ERROR expected open delimiter
|
assert!({one! two}); //~ ERROR expected one of `(`, `[`, or `{`, found `two`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
error: expected open delimiter
|
error: expected one of `(`, `[`, or `{`, found `two`
|
||||||
--> $DIR/issue-10536.rs:14:19
|
--> $DIR/issue-10536.rs:14:19
|
||||||
|
|
|
|
||||||
LL | assert!({one! two()});
|
LL | assert!({one! two()});
|
||||||
| ^^^ expected open delimiter
|
| ^^^ expected one of `(`, `[`, or `{`
|
||||||
|
|
||||||
error: expected open delimiter
|
error: expected one of `(`, `[`, or `{`, found `two`
|
||||||
--> $DIR/issue-10536.rs:18:19
|
--> $DIR/issue-10536.rs:18:19
|
||||||
|
|
|
|
||||||
LL | assert!({one! two});
|
LL | assert!({one! two});
|
||||||
| ^^^ expected open delimiter
|
| ^^^ expected one of `(`, `[`, or `{`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
foo! bar < //~ ERROR expected open delimiter
|
foo! bar < //~ ERROR expected one of `(`, `[`, or `{`, found `bar`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: expected open delimiter
|
error: expected one of `(`, `[`, or `{`, found `bar`
|
||||||
--> $DIR/macro-bad-delimiter-ident.rs:2:10
|
--> $DIR/macro-bad-delimiter-ident.rs:2:10
|
||||||
|
|
|
|
||||||
LL | foo! bar <
|
LL | foo! bar <
|
||||||
| ^^^ expected open delimiter
|
| ^^^ expected one of `(`, `[`, or `{`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue