Rollup merge of #120218 - compiler-errors:parse_macro_arg, r=calebcartwright,ytmimi
rustfmt: Check that a token can begin a nonterminal kind before parsing it as a macro arg r? ``@ytmimi`` and/or ``@calebcartwright`` cc ``@fmease`` I'm putting this on r-l/rust since it should fix the nightly rustfmt version. If you don't care about having this regression until the next rustfmt->rust sync, then I can move that PR over to r-l/rustfmt. --- > Any idea why the formatting would have changed [from #119099]? **Copied over explanation:** This has to do with the weirdness of the way that `parse_macro_arg` works. Unlike parsing nonterminal args in a macro-by-example, it eagerly tries, for example, to parse a type without checking that the beginning token may begin a type:bf967319e2/src/parse/macros/mod.rs (L54)
Contrast this to the nonterminal parsing code, which first checks that the nonterminal may begin with a given token:ef71f1047e/compiler/rustc_parse/src/parser/nonterminal.rs (L47)
In rust-lang/rust#119099, ``@fmease`` implemented a change so that `const Tr` would be parsed as `dyn const Tr` (a trait object to a const trait) in edition 2015. This is okay for the purposes of macros, because he explicitly made sure that `const` did not get added to the list of tokens that may begin a `:ty` nonterminal kind: https://github.com/rust-lang/rust/pull/119099#discussion_r1436996007 However, since rustfmt is not so careful about eagerly parsing macro args before checking that they're legal in macro position, this changed the way that the string of tokens is being parsed into macro args.
This commit is contained in:
commit
0b0f0be419
@ -1,7 +1,7 @@
|
|||||||
use rustc_ast::token::{Delimiter, TokenKind};
|
use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind};
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast::{ast, ptr};
|
use rustc_ast::{ast, ptr};
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
use rustc_parse::parser::{ForceCollect, Parser, Recovery};
|
||||||
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS};
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::symbol::{self, kw};
|
use rustc_span::symbol::{self, kw};
|
||||||
@ -15,7 +15,7 @@ pub(crate) mod cfg_if;
|
|||||||
pub(crate) mod lazy_static;
|
pub(crate) mod lazy_static;
|
||||||
|
|
||||||
fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
|
fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
|
||||||
stream_to_parser(sess, tokens, MACRO_ARGUMENTS)
|
stream_to_parser(sess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
|
fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
|
||||||
@ -24,21 +24,23 @@ fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser
|
|||||||
|
|
||||||
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||||
macro_rules! parse_macro_arg {
|
macro_rules! parse_macro_arg {
|
||||||
($macro_arg:ident, $parser:expr, $f:expr) => {
|
($macro_arg:ident, $nt_kind:expr, $try_parse:expr, $then:expr) => {
|
||||||
let mut cloned_parser = (*parser).clone();
|
let mut cloned_parser = (*parser).clone();
|
||||||
match $parser(&mut cloned_parser) {
|
if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) {
|
||||||
Ok(x) => {
|
match $try_parse(&mut cloned_parser) {
|
||||||
if parser.sess.dcx.has_errors().is_some() {
|
Ok(x) => {
|
||||||
parser.sess.dcx.reset_err_count();
|
if parser.sess.dcx.has_errors().is_some() {
|
||||||
} else {
|
parser.sess.dcx.reset_err_count();
|
||||||
// Parsing succeeded.
|
} else {
|
||||||
*parser = cloned_parser;
|
// Parsing succeeded.
|
||||||
return Some(MacroArg::$macro_arg($f(x)?));
|
*parser = cloned_parser;
|
||||||
|
return Some(MacroArg::$macro_arg($then(x)?));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
e.cancel();
|
||||||
|
parser.sess.dcx.reset_err_count();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
e.cancel();
|
|
||||||
parser.sess.dcx.reset_err_count();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -46,23 +48,27 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
|||||||
|
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Expr,
|
Expr,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(),
|
NonterminalKind::Expr,
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_expr(),
|
||||||
|x: ptr::P<ast::Expr>| Some(x)
|
|x: ptr::P<ast::Expr>| Some(x)
|
||||||
);
|
);
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Ty,
|
Ty,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(),
|
NonterminalKind::Ty,
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_ty(),
|
||||||
|x: ptr::P<ast::Ty>| Some(x)
|
|x: ptr::P<ast::Ty>| Some(x)
|
||||||
);
|
);
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Pat,
|
Pat,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None, None),
|
NonterminalKind::PatParam { inferred: false },
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None),
|
||||||
|x: ptr::P<ast::Pat>| Some(x)
|
|x: ptr::P<ast::Pat>| Some(x)
|
||||||
);
|
);
|
||||||
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Item,
|
Item,
|
||||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No),
|
NonterminalKind::Item,
|
||||||
|
|parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No),
|
||||||
|x: Option<ptr::P<ast::Item>>| x
|
|x: Option<ptr::P<ast::Item>>| x
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
m!(const N: usize = 0;);
|
@ -0,0 +1,3 @@
|
|||||||
|
m!(
|
||||||
|
const N: usize = 0;
|
||||||
|
);
|
Loading…
x
Reference in New Issue
Block a user