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());
|
||||
}
|
||||
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) {
|
||||
self.check_ident_token(cx, UnderMacro(false), ident);
|
||||
|
|
|
@ -244,7 +244,7 @@ impl<'a> Parser<'a> {
|
|||
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()?;
|
||||
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.
|
||||
if self.eat(&token::Not) {
|
||||
// MACRO INVOCATION expression
|
||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||
let args = self.parse_mac_args()?;
|
||||
hi = self.prev_span;
|
||||
ex = ExprKind::Mac(Mac {
|
||||
path,
|
||||
tts,
|
||||
delim,
|
||||
args,
|
||||
span: lo.to(hi),
|
||||
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::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
||||
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::ptr::P;
|
||||
use syntax::ThinVec;
|
||||
|
@ -437,16 +437,15 @@ impl<'a> Parser<'a> {
|
|||
// Item macro
|
||||
let path = self.parse_path(PathStyle::Mod)?;
|
||||
self.expect(&token::Not)?;
|
||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
|
||||
let args = self.parse_mac_args()?;
|
||||
if args.need_semicolon() && !self.eat(&token::Semi) {
|
||||
self.report_invalid_macro_expansion_item();
|
||||
}
|
||||
|
||||
let hi = self.prev_span;
|
||||
let mac = Mac {
|
||||
path,
|
||||
tts,
|
||||
delim,
|
||||
args,
|
||||
span: mac_lo.to(hi),
|
||||
prior_type_ascription: self.last_type_ascription,
|
||||
};
|
||||
|
@ -518,15 +517,14 @@ impl<'a> Parser<'a> {
|
|||
*at_end = true;
|
||||
|
||||
// eat a matched-delimiter token tree:
|
||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||
if delim != MacDelimiter::Brace {
|
||||
let args = self.parse_mac_args()?;
|
||||
if args.need_semicolon() {
|
||||
self.expect_semi()?;
|
||||
}
|
||||
|
||||
Ok(Some(Mac {
|
||||
path,
|
||||
tts,
|
||||
delim,
|
||||
args,
|
||||
span: lo.to(self.prev_span),
|
||||
prior_type_ascription: self.last_type_ascription,
|
||||
}))
|
||||
|
@ -1660,12 +1658,12 @@ impl<'a> Parser<'a> {
|
|||
self.bump();
|
||||
|
||||
let ident = self.parse_ident()?;
|
||||
let (delim, tokens) = self.expect_delimited_token_tree()?;
|
||||
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
|
||||
let args = self.parse_mac_args()?;
|
||||
if args.need_semicolon() && !self.eat(&token::Semi) {
|
||||
self.report_invalid_macro_expansion_item();
|
||||
}
|
||||
|
||||
(ident, ast::MacroDef { tokens, legacy: true })
|
||||
(ident, ast::MacroDef { tokens: args.inner_tokens(), legacy: true })
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::lexer::UnmatchedBrace;
|
|||
|
||||
use syntax::ast::{
|
||||
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;
|
||||
|
@ -1010,27 +1010,49 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
|
||||
let delim = match self.token.kind {
|
||||
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)
|
||||
fn parse_mac_args(&mut self) -> PResult<'a, P<MacArgs>> {
|
||||
self.parse_mac_args_common(true)
|
||||
}
|
||||
};
|
||||
let tts = match self.parse_token_tree() {
|
||||
TokenTree::Delimited(_, _, tts) => tts,
|
||||
|
||||
#[allow(dead_code)]
|
||||
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!(),
|
||||
}
|
||||
} 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,
|
||||
token::Bracket => MacDelimiter::Bracket,
|
||||
token::Brace => MacDelimiter::Brace,
|
||||
token::NoDelim => self.bug("unexpected no delimiter"),
|
||||
};
|
||||
Ok((delim, tts.into()))
|
||||
|
||||
MacArgs::Eq(eq_span, token_tree.into())
|
||||
} else {
|
||||
MacArgs::Empty
|
||||
}
|
||||
} else {
|
||||
return self.unexpected();
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_or_use_outer_attributes(
|
||||
|
|
|
@ -595,11 +595,10 @@ impl<'a> Parser<'a> {
|
|||
/// Parse macro invocation
|
||||
fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> {
|
||||
self.bump();
|
||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||
let args = self.parse_mac_args()?;
|
||||
let mac = Mac {
|
||||
path,
|
||||
tts,
|
||||
delim,
|
||||
args,
|
||||
span: lo.to(self.prev_span),
|
||||
prior_type_ascription: self.last_type_ascription,
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ use syntax::ThinVec;
|
|||
use syntax::ptr::P;
|
||||
use syntax::ast;
|
||||
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::token;
|
||||
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 style = if delim == MacDelimiter::Brace {
|
||||
let style = if delim == token::Brace {
|
||||
MacStmtStyle::Braces
|
||||
} else {
|
||||
MacStmtStyle::NoBraces
|
||||
|
@ -104,12 +105,11 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let mac = Mac {
|
||||
path,
|
||||
tts,
|
||||
delim,
|
||||
args,
|
||||
span: lo.to(hi),
|
||||
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 {
|
||||
StmtKind::Mac(P((mac, style, attrs.into())))
|
||||
}
|
||||
|
|
|
@ -177,11 +177,10 @@ impl<'a> Parser<'a> {
|
|||
let path = self.parse_path(PathStyle::Type)?;
|
||||
if self.eat(&token::Not) {
|
||||
// Macro invocation in type position
|
||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||
let args = self.parse_mac_args()?;
|
||||
let mac = Mac {
|
||||
path,
|
||||
tts,
|
||||
delim,
|
||||
args,
|
||||
span: lo.to(self.prev_span),
|
||||
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::source_map::{dummy_spanned, respan, Spanned};
|
||||
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::{Span, DUMMY_SP, ExpnId};
|
||||
|
@ -40,6 +40,7 @@ use rustc_index::vec::Idx;
|
|||
use rustc_serialize::{self, Decoder, Encoder};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
|
||||
use std::iter;
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1372,21 +1373,71 @@ pub enum Movability {
|
|||
Movable,
|
||||
}
|
||||
|
||||
/// Represents a macro invocation. The `Path` indicates which macro
|
||||
/// is being invoked, and the vector of token-trees contains the source
|
||||
/// of the macro invocation.
|
||||
///
|
||||
/// N.B., the additional ident for a `macro_rules`-style macro is actually
|
||||
/// stored in the enclosing item.
|
||||
/// Represents a macro invocation. The `path` indicates which macro
|
||||
/// is being invoked, and the `args` are arguments passed to it.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Mac {
|
||||
pub path: Path,
|
||||
pub delim: MacDelimiter,
|
||||
pub tts: TokenStream,
|
||||
pub args: P<MacArgs>,
|
||||
pub span: Span,
|
||||
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)]
|
||||
pub enum MacDelimiter {
|
||||
Parenthesis,
|
||||
|
@ -1394,12 +1445,6 @@ pub enum MacDelimiter {
|
|||
Brace,
|
||||
}
|
||||
|
||||
impl Mac {
|
||||
pub fn stream(&self) -> TokenStream {
|
||||
self.tts.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl MacDelimiter {
|
||||
crate fn to_token(self) -> DelimToken {
|
||||
match self {
|
||||
|
@ -1408,6 +1453,15 @@ impl MacDelimiter {
|
|||
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.
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#![feature(const_transmute)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(label_break_value)]
|
||||
#![feature(matches_macro)]
|
||||
#![feature(nll)]
|
||||
#![feature(try_trait)]
|
||||
#![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);
|
||||
}
|
||||
|
||||
// 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>(
|
||||
mut fp: FieldPat,
|
||||
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) {
|
||||
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_tts(tts);
|
||||
visit_mac_args(args, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||
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::comments;
|
||||
use crate::attr;
|
||||
|
@ -1097,9 +1097,8 @@ impl<'a> State<'a> {
|
|||
}
|
||||
ast::ForeignItemKind::Macro(ref m) => {
|
||||
self.print_mac(m);
|
||||
match m.delim {
|
||||
MacDelimiter::Brace => {},
|
||||
_ => self.s.word(";")
|
||||
if m.args.need_semicolon() {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1361,9 +1360,8 @@ impl<'a> State<'a> {
|
|||
}
|
||||
ast::ItemKind::Mac(ref mac) => {
|
||||
self.print_mac(mac);
|
||||
match mac.delim {
|
||||
MacDelimiter::Brace => {}
|
||||
_ => self.s.word(";"),
|
||||
if mac.args.need_semicolon() {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
ast::ItemKind::MacroDef(ref macro_def) => {
|
||||
|
@ -1578,9 +1576,8 @@ impl<'a> State<'a> {
|
|||
}
|
||||
ast::TraitItemKind::Macro(ref mac) => {
|
||||
self.print_mac(mac);
|
||||
match mac.delim {
|
||||
MacDelimiter::Brace => {}
|
||||
_ => self.s.word(";"),
|
||||
if mac.args.need_semicolon() {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1608,9 +1605,8 @@ impl<'a> State<'a> {
|
|||
}
|
||||
ast::ImplItemKind::Macro(ref mac) => {
|
||||
self.print_mac(mac);
|
||||
match mac.delim {
|
||||
MacDelimiter::Brace => {}
|
||||
_ => self.s.word(";"),
|
||||
if mac.args.need_semicolon() {
|
||||
self.s.word(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1775,7 +1771,7 @@ impl<'a> State<'a> {
|
|||
Some(MacHeader::Path(&m.path)),
|
||||
true,
|
||||
None,
|
||||
m.delim.to_token(),
|
||||
m.args.delim(),
|
||||
m.stream(),
|
||||
true,
|
||||
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 (`$(...)`).
|
||||
enum Frame {
|
||||
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
|
||||
// the previous results (from outside the 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 });
|
||||
result_stack.push(mem::take(&mut result));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::expand::{AstFragment, AstFragmentKind};
|
|||
|
||||
use syntax::ast;
|
||||
use syntax::source_map::{DUMMY_SP, dummy_spanned};
|
||||
use syntax::tokenstream::TokenStream;
|
||||
use syntax::mut_visit::*;
|
||||
use syntax::ptr::P;
|
||||
use syntax::ThinVec;
|
||||
|
@ -17,8 +16,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
|
|||
fn mac_placeholder() -> ast::Mac {
|
||||
ast::Mac {
|
||||
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
|
||||
tts: TokenStream::default().into(),
|
||||
delim: ast::MacDelimiter::Brace,
|
||||
args: P(ast::MacArgs::Empty),
|
||||
span: DUMMY_SP,
|
||||
prior_type_ascription: None,
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use syntax::token::{self, TokenKind};
|
|||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::{sym, Symbol};
|
||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||
use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||
use syntax_expand::base::*;
|
||||
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
|
||||
// context to pick up whichever is currently in scope.
|
||||
let sp = cx.with_call_site_ctxt(sp);
|
||||
let panic_call = Mac {
|
||||
path: Path::from_ident(Ident::new(sym::panic, sp)),
|
||||
tts: custom_message.unwrap_or_else(|| {
|
||||
let tokens = custom_message.unwrap_or_else(|| {
|
||||
TokenStream::from(TokenTree::token(
|
||||
TokenKind::lit(token::Str, Symbol::intern(&format!(
|
||||
"assertion failed: {}",
|
||||
|
@ -36,8 +34,11 @@ pub fn expand_assert<'cx>(
|
|||
)), None),
|
||||
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,
|
||||
prior_type_ascription: None,
|
||||
};
|
||||
|
|
|
@ -11,9 +11,9 @@ macro_rules! foo{
|
|||
pub fn main() {
|
||||
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
|
||||
// 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
|
||||
|
|
||||
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
|
||||
|
|
||||
LL | assert!({one! two});
|
||||
| ^^^ expected open delimiter
|
||||
| ^^^ expected one of `(`, `[`, or `{`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
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
|
||||
|
|
||||
LL | foo! bar <
|
||||
| ^^^ expected open delimiter
|
||||
| ^^^ expected one of `(`, `[`, or `{`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue