Capture tokens for Pat used in macro_rules! argument
This extends PR #73293 to handle patterns (Pat). Unlike expressions, patterns do not support custom attributes, so we only need to capture tokens during macro_rules! argument parsing.
This commit is contained in:
parent
f6049b60db
commit
607a190059
|
@ -550,6 +550,7 @@ pub struct Pat {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub kind: PatKind,
|
pub kind: PatKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub tokens: Option<TokenStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pat {
|
impl Pat {
|
||||||
|
@ -2138,6 +2139,7 @@ impl Param {
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
|
kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
|
||||||
span,
|
span,
|
||||||
|
tokens: None,
|
||||||
}),
|
}),
|
||||||
span,
|
span,
|
||||||
ty,
|
ty,
|
||||||
|
|
|
@ -1053,7 +1053,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
|
||||||
let Pat { id, kind, span } = pat.deref_mut();
|
let Pat { id, kind, span, tokens: _ } = pat.deref_mut();
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
match kind {
|
match kind {
|
||||||
PatKind::Wild | PatKind::Rest => {}
|
PatKind::Wild | PatKind::Rest => {}
|
||||||
|
|
|
@ -551,6 +551,7 @@ impl MacResult for MacEager {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: e.span,
|
span: e.span,
|
||||||
kind: PatKind::Lit(e),
|
kind: PatKind::Lit(e),
|
||||||
|
tokens: None,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -597,7 +598,7 @@ impl DummyResult {
|
||||||
|
|
||||||
/// A plain dummy pattern.
|
/// A plain dummy pattern.
|
||||||
pub fn raw_pat(sp: Span) -> ast::Pat {
|
pub fn raw_pat(sp: Span) -> ast::Pat {
|
||||||
ast::Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Wild, span: sp }
|
ast::Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Wild, span: sp, tokens: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A plain dummy type.
|
/// A plain dummy type.
|
||||||
|
|
|
@ -392,7 +392,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
|
pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
|
||||||
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span })
|
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
|
||||||
}
|
}
|
||||||
pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
|
pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
|
||||||
self.pat(span, PatKind::Wild)
|
self.pat(span, PatKind::Wild)
|
||||||
|
|
|
@ -38,7 +38,8 @@ pub fn placeholder(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
|
let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
|
||||||
let pat = || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span });
|
let pat =
|
||||||
|
|| P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
|
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
|
||||||
|
@ -85,6 +86,7 @@ pub fn placeholder(
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
kind: ast::PatKind::MacCall(mac_placeholder()),
|
kind: ast::PatKind::MacCall(mac_placeholder()),
|
||||||
|
tokens: None,
|
||||||
})),
|
})),
|
||||||
AstFragmentKind::Ty => {
|
AstFragmentKind::Ty => {
|
||||||
AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) }))
|
AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) }))
|
||||||
|
|
|
@ -263,6 +263,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
|
||||||
Nonterminal::NtItem(ref item) => {
|
Nonterminal::NtItem(ref item) => {
|
||||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||||
}
|
}
|
||||||
|
Nonterminal::NtPat(ref pat) => pat.tokens.clone(),
|
||||||
Nonterminal::NtIdent(ident, is_raw) => {
|
Nonterminal::NtIdent(ident, is_raw) => {
|
||||||
Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
|
Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
|
kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
|
||||||
span: ident.span,
|
span: ident.span,
|
||||||
|
tokens: None,
|
||||||
});
|
});
|
||||||
let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID };
|
let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID };
|
||||||
Param {
|
Param {
|
||||||
|
@ -83,7 +84,12 @@ impl RecoverQPath for Pat {
|
||||||
self.to_ty()
|
self.to_ty()
|
||||||
}
|
}
|
||||||
fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
|
fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
|
||||||
Self { span: path.span, kind: PatKind::Path(qself, path), id: ast::DUMMY_NODE_ID }
|
Self {
|
||||||
|
span: path.span,
|
||||||
|
kind: PatKind::Path(qself, path),
|
||||||
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
tokens: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,7 +1532,8 @@ impl<'a> Parser<'a> {
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
|
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
|
||||||
let pat = P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID });
|
let pat =
|
||||||
|
P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None });
|
||||||
Ok((pat, ty))
|
Ok((pat, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,14 @@ impl<'a> Parser<'a> {
|
||||||
Some(s) => token::NtStmt(s),
|
Some(s) => token::NtStmt(s),
|
||||||
None => return Err(self.struct_span_err(self.token.span, "expected a statement")),
|
None => return Err(self.struct_span_err(self.token.span, "expected a statement")),
|
||||||
},
|
},
|
||||||
NonterminalKind::Pat => token::NtPat(self.parse_pat(None)?),
|
NonterminalKind::Pat => {
|
||||||
|
let (mut pat, tokens) = self.collect_tokens(|this| this.parse_pat(None))?;
|
||||||
|
// We have have eaten an NtPat, which could already have tokens
|
||||||
|
if pat.tokens.is_none() {
|
||||||
|
pat.tokens = Some(tokens);
|
||||||
|
}
|
||||||
|
token::NtPat(pat)
|
||||||
|
}
|
||||||
NonterminalKind::Expr => {
|
NonterminalKind::Expr => {
|
||||||
let (mut expr, tokens) = self.collect_tokens(|this| this.parse_expr())?;
|
let (mut expr, tokens) = self.collect_tokens(|this| this.parse_expr())?;
|
||||||
// If we captured tokens during parsing (due to outer attributes),
|
// If we captured tokens during parsing (due to outer attributes),
|
||||||
|
|
|
@ -1007,6 +1007,6 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
|
fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
|
||||||
P(Pat { kind, span, id: ast::DUMMY_NODE_ID })
|
P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,6 +164,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
kind: PatKind::Wild,
|
kind: PatKind::Wild,
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
|
tokens: None,
|
||||||
});
|
});
|
||||||
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
|
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
// aux-build:test-macros.rs
|
// aux-build:test-macros.rs
|
||||||
// check-pass
|
// check-pass
|
||||||
|
// compile-flags: -Z span-debug
|
||||||
|
// normalize-stdout-test "#\d+" -> "#CTXT"
|
||||||
|
|
||||||
extern crate test_macros;
|
extern crate test_macros;
|
||||||
use test_macros::recollect;
|
use test_macros::print_bang;
|
||||||
|
|
||||||
macro_rules! use_expr {
|
macro_rules! use_expr {
|
||||||
($expr:expr) => {
|
($expr:expr) => {
|
||||||
recollect!($expr)
|
print_bang!($expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! use_pat {
|
||||||
|
($pat:pat) => {
|
||||||
|
print_bang!($pat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +25,10 @@ impl Foo {
|
||||||
fn use_self(self) {
|
fn use_self(self) {
|
||||||
drop(use_expr!(self));
|
drop(use_expr!(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_pat(use_pat!((a, b)): (u32, u32)) {
|
||||||
|
println!("Args: {} {}", a, b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
PRINT-BANG INPUT (DISPLAY): self
|
||||||
|
PRINT-BANG INPUT (DEBUG): TokenStream [
|
||||||
|
Group {
|
||||||
|
delimiter: None,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "self",
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:26:24: 26:28 (#CTXT),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:11:21: 11:26 (#CTXT),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
PRINT-BANG INPUT (DISPLAY): (a, b)
|
||||||
|
PRINT-BANG INPUT (DEBUG): TokenStream [
|
||||||
|
Group {
|
||||||
|
delimiter: None,
|
||||||
|
stream: TokenStream [
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "a",
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:29:27: 29:28 (#CTXT),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:29:28: 29:29 (#CTXT),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "b",
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:29:30: 29:31 (#CTXT),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:29:26: 29:32 (#CTXT),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/capture-macro-rules-invoke.rs:17:21: 17:25 (#CTXT),
|
||||||
|
},
|
||||||
|
]
|
|
@ -340,6 +340,7 @@ fn take_pat(from: &mut Pat) -> Pat {
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
kind: Wild,
|
kind: Wild,
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
|
tokens: None
|
||||||
};
|
};
|
||||||
mem::replace(from, dummy)
|
mem::replace(from, dummy)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue