diff options
| author | Aaron Hill <aa1ronham@gmail.com> | 2021-01-18 16:47:37 -0500 |
|---|---|---|
| committer | Aaron Hill <aa1ronham@gmail.com> | 2021-01-20 18:09:32 -0500 |
| commit | 11b1e370161dd09c095350c66f7b187fc9654ec6 (patch) | |
| tree | c46df174a600d0557fe310f927cdabfec2ef06fc /compiler/rustc_expand/src | |
| parent | a4cbb44ae2c80545db957763b502dc7f6ea22085 (diff) | |
| download | rust-11b1e370161dd09c095350c66f7b187fc9654ec6.tar.gz rust-11b1e370161dd09c095350c66f7b187fc9654ec6.zip | |
Force token collection to run when parsing nonterminals
Fixes #81007 Previously, we would fail to collect tokens in the proper place when only builtin attributes were present. As a result, we would end up with attribute tokens in the collected `TokenStream`, leading to duplication when we attempted to prepend the attributes from the AST node. We now explicitly track when token collection must be performed due to nomterminal parsing.
Diffstat (limited to 'compiler/rustc_expand/src')
| -rw-r--r-- | compiler/rustc_expand/src/expand.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/parse/tests.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/proc_macro.rs | 3 |
3 files changed, 7 insertions, 5 deletions
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 16913dbb1ab..5d398935ce8 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -20,7 +20,7 @@ use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{struct_span_err, Applicability, PResult}; use rustc_feature::Features; -use rustc_parse::parser::{AttemptLocalParseRecovery, Parser}; +use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; @@ -913,7 +913,7 @@ pub fn parse_ast_fragment<'a>( Ok(match kind { AstFragmentKind::Items => { let mut items = SmallVec::new(); - while let Some(item) = this.parse_item()? { + while let Some(item) = this.parse_item(ForceCollect::No)? { items.push(item); } AstFragment::Items(items) diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index 643305f153c..f4fcaf5c0a4 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -8,6 +8,7 @@ use rustc_ast::{self as ast, PatKind}; use rustc_ast_pretty::pprust::item_to_string; use rustc_errors::PResult; use rustc_parse::new_parser_from_source_str; +use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; use rustc_span::symbol::{kw, sym, Symbol}; @@ -29,7 +30,7 @@ fn parse_item_from_source_str( source: String, sess: &ParseSess, ) -> PResult<'_, Option<P<ast::Item>>> { - new_parser_from_source_str(sess, name, source).parse_item() + new_parser_from_source_str(sess, name, source).parse_item(ForceCollect::No) } // Produces a `rustc_span::span`. @@ -44,7 +45,7 @@ fn string_to_expr(source_str: String) -> P<ast::Expr> { /// Parses a string, returns an item. fn string_to_item(source_str: String) -> Option<P<ast::Item>> { - with_error_checking_parse(source_str, &sess(), |p| p.parse_item()) + with_error_checking_parse(source_str, &sess(), |p| p.parse_item(ForceCollect::No)) } #[should_panic] diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 02129e9b5e5..6779734cfc1 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -9,6 +9,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability, ErrorReported}; use rustc_lexer::is_ident; use rustc_parse::nt_to_tokenstream; +use rustc_parse::parser::ForceCollect; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -117,7 +118,7 @@ impl MultiItemModifier for ProcMacroDerive { let mut items = vec![]; loop { - match parser.parse_item() { + match parser.parse_item(ForceCollect::No) { Ok(None) => break, Ok(Some(item)) => { if is_stmt { |
