From 287db04636ffefa3fdaa39fe0fdcc3cf75b60444 Mon Sep 17 00:00:00 2001 From: Catherine Date: Mon, 24 Jul 2023 04:55:47 +0000 Subject: Specify macro is invalid in certain contexts --- compiler/rustc_parse/src/parser/diagnostics.rs | 37 +++++++++++++++----------- compiler/rustc_parse/src/parser/item.rs | 26 ++++++++++++------ compiler/rustc_parse/src/parser/pat.rs | 12 +++++++-- 3 files changed, 49 insertions(+), 26 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c3cf6437afa..3eed3ed9e1b 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2591,6 +2591,7 @@ impl<'a> Parser<'a> { pub(crate) fn maybe_recover_unexpected_comma( &mut self, lo: Span, + is_mac_invoc: bool, rt: CommaRecoveryMode, ) -> PResult<'a, ()> { if self.token != token::Comma { @@ -2611,24 +2612,28 @@ impl<'a> Parser<'a> { let seq_span = lo.to(self.prev_token.span); let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - err.multipart_suggestion( - format!( - "try adding parentheses to match on a tuple{}", - if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, - ), - vec![ - (seq_span.shrink_to_lo(), "(".to_string()), - (seq_span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); - if let CommaRecoveryMode::EitherTupleOrPipe = rt { - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(',', " |"), + if is_mac_invoc { + err.note(fluent::parse_macro_expands_to_match_arm); + } else { + err.multipart_suggestion( + format!( + "try adding parentheses to match on a tuple{}", + if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." }, + ), + vec![ + (seq_span.shrink_to_lo(), "(".to_string()), + (seq_span.shrink_to_hi(), ")".to_string()), + ], Applicability::MachineApplicable, ); + if let CommaRecoveryMode::EitherTupleOrPipe = rt { + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(',', " |"), + Applicability::MachineApplicable, + ); + } } } Err(err) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 1470180dea7..6ec3a1ff1a5 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,8 +1,8 @@ -use crate::errors; - use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; +use crate::errors::{self, MacroExpandsToAdtField}; +use crate::fluent_generated as fluent; use ast::StaticItem; use rustc_ast::ast::*; use rustc_ast::ptr::P; @@ -1342,6 +1342,13 @@ impl<'a> Parser<'a> { } let ident = this.parse_field_ident("enum", vlo)?; + if this.token == token::Not { + return this.unexpected().map_err(|mut err| { + err.note(fluent::parse_macro_expands_to_enum_variant); + err + }); + } + let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { // Parse a struct variant. let (fields, recovered) = @@ -1369,7 +1376,7 @@ impl<'a> Parser<'a> { Ok((Some(vr), TrailingToken::MaybeComma)) }, - ).map_err(|mut err|{ + ).map_err(|mut err| { err.help("enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`"); err }) @@ -1691,9 +1698,10 @@ impl<'a> Parser<'a> { Ok(a_var) } - fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { + fn expect_field_ty_separator(&mut self, adt_ty: &str) -> PResult<'a, ()> { if let Err(mut err) = self.expect(&token::Colon) { let sm = self.sess.source_map(); + let mac_invoc = self.token.kind == token::Not; let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); let semi_typo = self.token.kind == token::Semi && self.look_ahead(1, |t| { @@ -1705,7 +1713,9 @@ impl<'a> Parser<'a> { _ => true, } }); - if eq_typo || semi_typo { + if mac_invoc { + err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit(); + } else if eq_typo || semi_typo { self.bump(); // Gracefully handle small typos. err.span_suggestion_short( @@ -1713,8 +1723,8 @@ impl<'a> Parser<'a> { "field names and their types are separated with `:`", ":", Applicability::MachineApplicable, - ); - err.emit(); + ) + .emit(); } else { return Err(err); } @@ -1731,7 +1741,7 @@ impl<'a> Parser<'a> { attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; - self.expect_field_ty_separator()?; + self.expect_field_ty_separator(adt_ty)?; let ty = self.parse_ty()?; if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { self.sess.emit_err(errors::SingleColonStructType { span: self.token.span }); diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 14891c45d81..b477453615d 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -135,7 +135,11 @@ impl<'a> Parser<'a> { // Parse the first pattern (`p_0`). let mut first_pat = self.parse_pat_no_top_alt(expected)?; if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma(first_pat.span, rt)?; + self.maybe_recover_unexpected_comma( + first_pat.span, + matches!(first_pat.kind, PatKind::MacCall(_)), + rt, + )?; } // If the next token is not a `|`, @@ -177,7 +181,11 @@ impl<'a> Parser<'a> { err })?; if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma(pat.span, rt)?; + self.maybe_recover_unexpected_comma( + pat.span, + matches!(pat.kind, PatKind::MacCall(_)), + rt, + )?; } pats.push(pat); } -- cgit 1.4.1-3-g733a5 From dece622ee48d9744d6e64891a734e8fd25eac903 Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Mon, 24 Jul 2023 17:05:10 +0000 Subject: Recover from some macros --- compiler/rustc_parse/src/parser/item.rs | 46 ++++++++++++---- compiler/rustc_parse/src/parser/pat.rs | 6 +-- tests/ui/parser/macro/macro-expand-to-field-2.rs | 16 ------ .../ui/parser/macro/macro-expand-to-field-2.stderr | 18 ------- tests/ui/parser/macro/macro-expand-to-field-3.rs | 15 ------ .../ui/parser/macro/macro-expand-to-field-3.stderr | 19 ------- tests/ui/parser/macro/macro-expand-to-field.rs | 41 ++++++++++++-- tests/ui/parser/macro/macro-expand-to-field.stderr | 63 +++++++++++++++++----- tests/ui/parser/macro/macro-expand-to-match-arm.rs | 2 + 9 files changed, 124 insertions(+), 102 deletions(-) delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-2.rs delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-2.stderr delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-3.rs delete mode 100644 tests/ui/parser/macro/macro-expand-to-field-3.stderr (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6ec3a1ff1a5..7b479067ecd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1343,10 +1343,14 @@ impl<'a> Parser<'a> { let ident = this.parse_field_ident("enum", vlo)?; if this.token == token::Not { - return this.unexpected().map_err(|mut err| { - err.note(fluent::parse_macro_expands_to_enum_variant); - err - }); + if let Err(mut err) = this.unexpected::<()>() { + err.note(fluent::parse_macro_expands_to_enum_variant).emit(); + } + + this.bump(); + this.parse_delim_args()?; + + return Ok((None, TrailingToken::MaybeComma)); } let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) { @@ -1586,7 +1590,8 @@ impl<'a> Parser<'a> { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; - Ok((this.parse_single_struct_field(adt_ty, lo, vis, attrs)?, TrailingToken::None)) + this.parse_single_struct_field(adt_ty, lo, vis, attrs) + .map(|field| (field, TrailingToken::None)) }) } @@ -1698,10 +1703,9 @@ impl<'a> Parser<'a> { Ok(a_var) } - fn expect_field_ty_separator(&mut self, adt_ty: &str) -> PResult<'a, ()> { + fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { if let Err(mut err) = self.expect(&token::Colon) { let sm = self.sess.source_map(); - let mac_invoc = self.token.kind == token::Not; let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); let semi_typo = self.token.kind == token::Semi && self.look_ahead(1, |t| { @@ -1713,9 +1717,7 @@ impl<'a> Parser<'a> { _ => true, } }); - if mac_invoc { - err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit(); - } else if eq_typo || semi_typo { + if eq_typo || semi_typo { self.bump(); // Gracefully handle small typos. err.span_suggestion_short( @@ -1741,7 +1743,29 @@ impl<'a> Parser<'a> { attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; - self.expect_field_ty_separator(adt_ty)?; + // Parse the macro invocation and recover + if self.token.kind == token::Not { + if let Err(mut err) = self.unexpected::() { + err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit(); + self.bump(); + self.parse_delim_args()?; + return Ok(FieldDef { + span: DUMMY_SP, + ident: None, + vis, + id: DUMMY_NODE_ID, + ty: P(Ty { + id: DUMMY_NODE_ID, + kind: TyKind::Err, + span: DUMMY_SP, + tokens: None, + }), + attrs, + is_placeholder: false, + }); + } + } + self.expect_field_ty_separator()?; let ty = self.parse_ty()?; if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) { self.sess.emit_err(errors::SingleColonStructType { span: self.token.span }); diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b477453615d..58c00ebdea0 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -181,11 +181,7 @@ impl<'a> Parser<'a> { err })?; if rc == RecoverComma::Yes { - self.maybe_recover_unexpected_comma( - pat.span, - matches!(pat.kind, PatKind::MacCall(_)), - rt, - )?; + self.maybe_recover_unexpected_comma(pat.span, false, rt)?; } pats.push(pat); } diff --git a/tests/ui/parser/macro/macro-expand-to-field-2.rs b/tests/ui/parser/macro/macro-expand-to-field-2.rs deleted file mode 100644 index 2f806bcea84..00000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![no_main] - -macro_rules! field { - ($name:ident:$type:ty) => { - $name:$type - }; -} - -enum EnumVariantField { - Named { //~ NOTE while parsing this struct - field!(oopsies:()), //~ NOTE macros cannot expand to struct fields - //~^ ERROR expected `:`, found `!` - //~^^ ERROR expected `,`, or `}`, found `(` - //~^^^ NOTE expected `:` - }, -} diff --git a/tests/ui/parser/macro/macro-expand-to-field-2.stderr b/tests/ui/parser/macro/macro-expand-to-field-2.stderr deleted file mode 100644 index 8c3758173fe..00000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-2.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: expected `:`, found `!` - --> $DIR/macro-expand-to-field-2.rs:11:14 - | -LL | field!(oopsies:()), - | ^ expected `:` - | - = note: macros cannot expand to struct fields - -error: expected `,`, or `}`, found `(` - --> $DIR/macro-expand-to-field-2.rs:11:15 - | -LL | Named { - | ----- while parsing this struct -LL | field!(oopsies:()), - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/macro/macro-expand-to-field-3.rs b/tests/ui/parser/macro/macro-expand-to-field-3.rs deleted file mode 100644 index 0a8b655e0dc..00000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![no_main] - -macro_rules! field { - ($name:ident:$type:ty) => { - $name:$type - }; -} - -union EnumVariantField { //~ NOTE while parsing this union - A: u32, - field!(oopsies:()), //~ NOTE macros cannot expand to union fields - //~^ ERROR expected `:`, found `!` - //~^^ ERROR expected `,`, or `}`, found `(` - //~^^^ NOTE expected `:` -} diff --git a/tests/ui/parser/macro/macro-expand-to-field-3.stderr b/tests/ui/parser/macro/macro-expand-to-field-3.stderr deleted file mode 100644 index 360b2bf793b..00000000000 --- a/tests/ui/parser/macro/macro-expand-to-field-3.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: expected `:`, found `!` - --> $DIR/macro-expand-to-field-3.rs:11:10 - | -LL | field!(oopsies:()), - | ^ expected `:` - | - = note: macros cannot expand to union fields - -error: expected `,`, or `}`, found `(` - --> $DIR/macro-expand-to-field-3.rs:11:11 - | -LL | union EnumVariantField { - | ---------------- while parsing this union -LL | A: u32, -LL | field!(oopsies:()), - | ^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/parser/macro/macro-expand-to-field.rs b/tests/ui/parser/macro/macro-expand-to-field.rs index 38055a3bbb2..fd1d408e726 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.rs +++ b/tests/ui/parser/macro/macro-expand-to-field.rs @@ -12,15 +12,46 @@ macro_rules! variant { } } -struct Struct { //~ NOTE while parsing this struct +struct Struct { field!(bar:u128), //~ NOTE macros cannot expand to struct fields - //~^ ERROR expected `:`, found `!` - //~^^ NOTE expected `:` - //~^^^ ERROR expected `,`, or `}`, found `(` + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this + a: u32, + b: u32, + field!(recovers:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this } -enum EnumVariant { //~ NOTE while parsing this enum +enum EnumVariant { variant!(whoops), //~ NOTE macros cannot expand to enum variants //~^ ERROR unexpected token: `!` //~^^ NOTE unexpected token after this + U32, + F64, + variant!(recovers), //~ NOTE macros cannot expand to enum variants + //~^ ERROR unexpected token: `!` + //~^^ NOTE unexpected token after this +} + +enum EnumVariantField { + Named { + field!(oopsies:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this + field!(oopsies2:()), //~ NOTE macros cannot expand to struct fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this + }, +} + +union Union { + A: u32, + field!(oopsies:()), //~ NOTE macros cannot expand to union fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this + B: u32, + field!(recovers:()), //~ NOTE macros cannot expand to union fields + //~^ ERROR unexpected token: `!` + //~^^ unexpected token after this } diff --git a/tests/ui/parser/macro/macro-expand-to-field.stderr b/tests/ui/parser/macro/macro-expand-to-field.stderr index 3f7fad334ec..108b68b481f 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.stderr +++ b/tests/ui/parser/macro/macro-expand-to-field.stderr @@ -1,29 +1,66 @@ -error: expected `:`, found `!` +error: unexpected token: `!` --> $DIR/macro-expand-to-field.rs:16:10 | LL | field!(bar:u128), - | ^ expected `:` + | ^ unexpected token after this | = note: macros cannot expand to struct fields -error: expected `,`, or `}`, found `(` - --> $DIR/macro-expand-to-field.rs:16:11 +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:21:10 | -LL | struct Struct { - | ------ while parsing this struct -LL | field!(bar:u128), - | ^ +LL | field!(recovers:()), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:23:12 + --> $DIR/macro-expand-to-field.rs:27:12 | -LL | enum EnumVariant { - | ----------- while parsing this enum LL | variant!(whoops), | ^ unexpected token after this | = note: macros cannot expand to enum variants - = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` -error: aborting due to 3 previous errors +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:32:12 + | +LL | variant!(recovers), + | ^ unexpected token after this + | + = note: macros cannot expand to enum variants + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:39:14 + | +LL | field!(oopsies:()), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:42:14 + | +LL | field!(oopsies2:()), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:50:10 + | +LL | field!(oopsies:()), + | ^ unexpected token after this + | + = note: macros cannot expand to union fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:54:10 + | +LL | field!(recovers:()), + | ^ unexpected token after this + | + = note: macros cannot expand to union fields + +error: aborting due to 8 previous errors diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index 043bf371902..c176e8bbd9d 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -10,6 +10,8 @@ fn main() { Some(1) => {}, arm!(None => {}), //~ NOTE macros cannot expand to match arms //~^ ERROR unexpected `,` in pattern + // doesn't recover + Some(2) => {}, _ => {}, }; } -- cgit 1.4.1-3-g733a5 From 8e32dade71ad57978786537ec41c13222fd14611 Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 30 Jul 2023 15:49:33 +0800 Subject: parser: more friendly hints for handling `async move` in the 2015 edition --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 7 +++++++ compiler/rustc_parse/src/parser/diagnostics.rs | 15 +++++++++++---- tests/ui/parser/issues/issue-114219.rs | 4 ++++ tests/ui/parser/issues/issue-114219.stderr | 8 ++++++++ 5 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tests/ui/parser/issues/issue-114219.rs create mode 100644 tests/ui/parser/issues/issue-114219.stderr (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 83d96ad8e76..aec27060fed 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -23,6 +23,8 @@ parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or late parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015 .label = to use `async fn`, switch to Rust 2018 or later +parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later + parse_async_move_order_incorrect = the order of `move` and `async` is incorrect .suggestion = try switching the order diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 06c09960727..8ac30a6a5fe 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1434,6 +1434,13 @@ pub(crate) struct AsyncBlockIn2015 { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_async_move_block_in_2015)] +pub(crate) struct AsyncMoveBlockIn2015 { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_self_argument_pointer)] pub(crate) struct SelfArgumentPointer { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index e6de51a673c..6156ebec230 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -4,10 +4,11 @@ use super::{ TokenExpectType, TokenType, }; use crate::errors::{ - AmbiguousPlus, AttributeOnParamType, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi, - ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg, - ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, - DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, + AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, BadQPathStage2, BadTypePlus, + BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained, + ComparisonOperatorsCannotBeChainedSugg, ConstGenericWithoutBraces, + ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, DocCommentOnParamType, + DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg, @@ -573,6 +574,12 @@ impl<'a> Parser<'a> { return Err(self.sess.create_err(UseEqInstead { span: self.token.span })); } + if self.token.is_keyword(kw::Move) && self.prev_token.is_keyword(kw::Async) { + // The 2015 edition is in use because parsing of `async move` has failed. + let span = self.prev_token.span.to(self.token.span); + return Err(self.sess.create_err(AsyncMoveBlockIn2015 { span })); + } + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { diff --git a/tests/ui/parser/issues/issue-114219.rs b/tests/ui/parser/issues/issue-114219.rs new file mode 100644 index 00000000000..332258b628c --- /dev/null +++ b/tests/ui/parser/issues/issue-114219.rs @@ -0,0 +1,4 @@ +fn main() { + async move {}; + //~^ ERROR `async move` blocks are only allowed in Rust 2018 or later +} diff --git a/tests/ui/parser/issues/issue-114219.stderr b/tests/ui/parser/issues/issue-114219.stderr new file mode 100644 index 00000000000..90dcdc42775 --- /dev/null +++ b/tests/ui/parser/issues/issue-114219.stderr @@ -0,0 +1,8 @@ +error: `async move` blocks are only allowed in Rust 2018 or later + --> $DIR/issue-114219.rs:2:5 + | +LL | async move {}; + | ^^^^^^^^^^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From d9f2fdfaed8d18ede6d113426279c86d84d92445 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 31 Jul 2023 15:47:19 +1000 Subject: `parse_all_token_trees` cannot fail. --- compiler/rustc_parse/src/parser/mod.rs | 4 ++-- src/librustdoc/clean/render_macro_matchers.rs | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 57778d67098..b452eb6a401 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1288,12 +1288,12 @@ impl<'a> Parser<'a> { } /// Parses a stream of tokens into a list of `TokenTree`s, up to EOF. - pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec> { + pub fn parse_all_token_trees(&mut self) -> Vec { let mut tts = Vec::new(); while self.token != token::Eof { tts.push(self.parse_token_tree()); } - Ok(tts) + tts } pub fn parse_tokens(&mut self) -> TokenStream { diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index ef38ca3c16c..b6120e814df 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -76,13 +76,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option reparsed_trees, - Err(diagnostic) => { - diagnostic.cancel(); - return None; - } - }; + let mut reparsed_trees = parser.parse_all_token_trees(); if reparsed_trees.len() != 1 { return None; } -- cgit 1.4.1-3-g733a5 From db7b07aa028b65b4d85610e81fecb0d2382b8c76 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 31 Jul 2023 15:51:08 +1000 Subject: Inline and remove `parse_all_token_trees`. It has a single call site. --- compiler/rustc_parse/src/parser/mod.rs | 11 +---------- src/librustdoc/clean/render_macro_matchers.rs | 5 ++++- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b452eb6a401..4b23f5a6de1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1251,7 +1251,7 @@ impl<'a> Parser<'a> { } /// Parses a single token tree from the input. - pub(crate) fn parse_token_tree(&mut self) -> TokenTree { + pub fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { // Grab the tokens within the delimiters. @@ -1287,15 +1287,6 @@ impl<'a> Parser<'a> { } } - /// Parses a stream of tokens into a list of `TokenTree`s, up to EOF. - pub fn parse_all_token_trees(&mut self) -> Vec { - let mut tts = Vec::new(); - while self.token != token::Eof { - tts.push(self.parse_token_tree()); - } - tts - } - pub fn parse_tokens(&mut self) -> TokenStream { let mut result = Vec::new(); loop { diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index b6120e814df..b3dc0f63e45 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -76,7 +76,10 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option Date: Mon, 31 Jul 2023 16:15:54 +1000 Subject: Move `TokenCursor::num_next_calls` into `Parser` and rename it. It's more of a `Parser`-level concern than a `TokenCursor`-level concern. Also, `num_bump_calls` is a more accurate name, because it's incremented in `Parser::bump`. --- compiler/rustc_parse/src/parser/attr.rs | 6 +++--- compiler/rustc_parse/src/parser/attr_wrapper.rs | 13 ++++++------- compiler/rustc_parse/src/parser/mod.rs | 13 +++++-------- 3 files changed, 14 insertions(+), 18 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index ee0abba1c17..104de47b97d 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -36,7 +36,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { let mut outer_attrs = ast::AttrVec::new(); let mut just_parsed_doc_comment = false; - let start_pos = self.token_cursor.num_next_calls; + let start_pos = self.num_bump_calls; loop { let attr = if self.check(&token::Pound) { let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span); @@ -277,7 +277,7 @@ impl<'a> Parser<'a> { pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> { let mut attrs = ast::AttrVec::new(); loop { - let start_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); + let start_pos: u32 = self.num_bump_calls.try_into().unwrap(); // Only try to parse if it is an inner attribute (has `!`). let attr = if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) { Some(self.parse_attribute(InnerAttrPolicy::Permitted)?) @@ -298,7 +298,7 @@ impl<'a> Parser<'a> { None }; if let Some(attr) = attr { - let end_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap(); + let end_pos: u32 = self.num_bump_calls.try_into().unwrap(); // If we are currently capturing tokens, mark the location of this inner attribute. // If capturing ends up creating a `LazyAttrTokenStream`, we will include // this replace range with it, removing the inner attribute from the final diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 158ab2a2956..10c2066ef6c 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -213,6 +213,7 @@ impl<'a> Parser<'a> { let start_token = (self.token.clone(), self.token_spacing); let cursor_snapshot = self.token_cursor.clone(); + let start_pos = self.num_bump_calls; let has_outer_attrs = !attrs.attrs.is_empty(); let prev_capturing = std::mem::replace(&mut self.capture_state.capturing, Capturing::Yes); @@ -273,8 +274,7 @@ impl<'a> Parser<'a> { let replace_ranges_end = self.capture_state.replace_ranges.len(); - let cursor_snapshot_next_calls = cursor_snapshot.num_next_calls; - let mut end_pos = self.token_cursor.num_next_calls; + let mut end_pos = self.num_bump_calls; let mut captured_trailing = false; @@ -306,7 +306,7 @@ impl<'a> Parser<'a> { end_pos += 1; } - let num_calls = end_pos - cursor_snapshot_next_calls; + let num_calls = end_pos - start_pos; // If we have no attributes, then we will never need to // use any replace ranges. @@ -316,7 +316,7 @@ impl<'a> Parser<'a> { // Grab any replace ranges that occur *inside* the current AST node. // We will perform the actual replacement when we convert the `LazyAttrTokenStream` // to an `AttrTokenStream`. - let start_calls: u32 = cursor_snapshot_next_calls.try_into().unwrap(); + let start_calls: u32 = start_pos.try_into().unwrap(); self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] .iter() .cloned() @@ -359,8 +359,7 @@ impl<'a> Parser<'a> { // with a `FlatToken::AttrTarget`. If this AST node is inside an item // that has `#[derive]`, then this will allow us to cfg-expand this // AST node. - let start_pos = - if has_outer_attrs { attrs.start_pos } else { cursor_snapshot_next_calls }; + let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos }; let new_tokens = vec![(FlatToken::AttrTarget(attr_data), Spacing::Alone)]; assert!( @@ -464,6 +463,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(AttrWrapper, 16); - static_assert_size!(LazyAttrTokenStreamImpl, 120); + static_assert_size!(LazyAttrTokenStreamImpl, 112); // tidy-alphabetical-end } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4b23f5a6de1..2a1524f108a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -135,9 +135,9 @@ pub struct Parser<'a> { pub capture_cfg: bool, restrictions: Restrictions, expected_tokens: Vec, - // Important: This must only be advanced from `bump` to ensure that - // `token_cursor.num_next_calls` is updated properly. token_cursor: TokenCursor, + // The number of calls to `bump`, i.e. the position in the token stream. + num_bump_calls: usize, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. @@ -224,9 +224,6 @@ struct TokenCursor { // because it's the outermost token stream which never has delimiters. stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>, - // Counts the number of calls to `{,inlined_}next`. - num_next_calls: usize, - // During parsing, we may sometimes need to 'unglue' a // glued token into two component tokens // (e.g. '>>' into '>' and '>), so that the parser @@ -402,9 +399,9 @@ impl<'a> Parser<'a> { token_cursor: TokenCursor { tree_cursor: stream.into_trees(), stack: Vec::new(), - num_next_calls: 0, break_last_token: false, }, + num_bump_calls: 0, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, last_unexpected_token_span: None, @@ -1049,7 +1046,7 @@ impl<'a> Parser<'a> { // Note: destructuring here would give nicer code, but it was found in #96210 to be slower // than `.0`/`.1` access. let mut next = self.token_cursor.inlined_next(); - self.token_cursor.num_next_calls += 1; + self.num_bump_calls += 1; // We've retrieved an token from the underlying // cursor, so we no longer need to worry about // an unglued token. See `break_and_eat` for more details @@ -1446,7 +1443,7 @@ impl<'a> Parser<'a> { } pub fn approx_token_stream_pos(&self) -> usize { - self.token_cursor.num_next_calls + self.num_bump_calls } } -- cgit 1.4.1-3-g733a5 From 6fc2c481e5a7daf1873ccc34926f1c0387979569 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 31 Jul 2023 16:36:27 +1000 Subject: Move `TokenCursor::break_last_token` into `Parser`. Similar to the last commit, it's more of a `Parser`-level concern than a `TokenCursor`-level concern. And the struct size reductions are nice. After this change, `TokenCursor` is as minimal as possible (two fields and two methods) which is nice. --- compiler/rustc_parse/src/parser/attr_wrapper.rs | 11 ++---- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 51 ++++++++++--------------- 3 files changed, 25 insertions(+), 39 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 10c2066ef6c..5d6c574baa6 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -301,7 +301,7 @@ impl<'a> Parser<'a> { // then extend the range of captured tokens to include it, since the parser // was not actually bumped past it. When the `LazyAttrTokenStream` gets converted // into an `AttrTokenStream`, we will create the proper token. - if self.token_cursor.break_last_token { + if self.break_last_token { assert!(!captured_trailing, "Cannot set break_last_token and have trailing token"); end_pos += 1; } @@ -331,7 +331,7 @@ impl<'a> Parser<'a> { start_token, num_calls, cursor_snapshot, - break_last_token: self.token_cursor.break_last_token, + break_last_token: self.break_last_token, replace_ranges, }); @@ -362,10 +362,7 @@ impl<'a> Parser<'a> { let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos }; let new_tokens = vec![(FlatToken::AttrTarget(attr_data), Spacing::Alone)]; - assert!( - !self.token_cursor.break_last_token, - "Should not have unglued last token with cfg attr" - ); + assert!(!self.break_last_token, "Should not have unglued last token with cfg attr"); let range: Range = (start_pos.try_into().unwrap())..(end_pos.try_into().unwrap()); self.capture_state.replace_ranges.push((range, new_tokens)); self.capture_state.replace_ranges.extend(inner_attr_replace_ranges); @@ -463,6 +460,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(AttrWrapper, 16); - static_assert_size!(LazyAttrTokenStreamImpl, 112); + static_assert_size!(LazyAttrTokenStreamImpl, 104); // tidy-alphabetical-end } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 55f857aa31c..975dafecb10 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1167,7 +1167,7 @@ impl<'a> Parser<'a> { DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => { assert!(suffix.is_none()); // Analogous to `Self::break_and_eat` - self.token_cursor.break_last_token = true; + self.break_last_token = true; // This might work, in cases like `1. 2`, and might not, // in cases like `offset_of!(Ty, 1.)`. It depends on what comes // after the float-like token, and therefore we have to make diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2a1524f108a..27a8af630ce 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -138,6 +138,21 @@ pub struct Parser<'a> { token_cursor: TokenCursor, // The number of calls to `bump`, i.e. the position in the token stream. num_bump_calls: usize, + // During parsing we may sometimes need to 'unglue' a glued token into two + // component tokens (e.g. '>>' into '>' and '>), so the parser can consume + // them one at a time. This process bypasses the normal capturing mechanism + // (e.g. `num_bump_calls` will not be incremented), since the 'unglued' + // tokens due not exist in the original `TokenStream`. + // + // If we end up consuming both unglued tokens, this is not an issue. We'll + // end up capturing the single 'glued' token. + // + // However, sometimes we may want to capture just the first 'unglued' + // token. For example, capturing the `Vec` in `Option>` + // requires us to unglue the trailing `>>` token. The `break_last_token` + // field is used to track this token. It gets appended to the captured + // stream when we evaluate a `LazyAttrTokenStream`. + break_last_token: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. @@ -161,7 +176,7 @@ pub struct Parser<'a> { // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 272); +rustc_data_structures::static_assert_size!(Parser<'_>, 264); /// Stores span information about a closure. #[derive(Clone)] @@ -223,29 +238,6 @@ struct TokenCursor { // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters // because it's the outermost token stream which never has delimiters. stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>, - - // During parsing, we may sometimes need to 'unglue' a - // glued token into two component tokens - // (e.g. '>>' into '>' and '>), so that the parser - // can consume them one at a time. This process - // bypasses the normal capturing mechanism - // (e.g. `num_next_calls` will not be incremented), - // since the 'unglued' tokens due not exist in - // the original `TokenStream`. - // - // If we end up consuming both unglued tokens, - // then this is not an issue - we'll end up - // capturing the single 'glued' token. - // - // However, in certain circumstances, we may - // want to capture just the first 'unglued' token. - // For example, capturing the `Vec` - // in `Option>` requires us to unglue - // the trailing `>>` token. The `break_last_token` - // field is used to track this token - it gets - // appended to the captured stream when - // we evaluate a `LazyAttrTokenStream`. - break_last_token: bool, } impl TokenCursor { @@ -396,12 +388,9 @@ impl<'a> Parser<'a> { capture_cfg: false, restrictions: Restrictions::empty(), expected_tokens: Vec::new(), - token_cursor: TokenCursor { - tree_cursor: stream.into_trees(), - stack: Vec::new(), - break_last_token: false, - }, + token_cursor: TokenCursor { tree_cursor: stream.into_trees(), stack: Vec::new() }, num_bump_calls: 0, + break_last_token: false, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, last_unexpected_token_span: None, @@ -704,7 +693,7 @@ impl<'a> Parser<'a> { // If we consume any additional tokens, then this token // is not needed (we'll capture the entire 'glued' token), // and `bump` will set this field to `None` - self.token_cursor.break_last_token = true; + self.break_last_token = true; // Use the spacing of the glued token as the spacing // of the unglued second token. self.bump_with((Token::new(second, second_span), self.token_spacing)); @@ -1050,7 +1039,7 @@ impl<'a> Parser<'a> { // We've retrieved an token from the underlying // cursor, so we no longer need to worry about // an unglued token. See `break_and_eat` for more details - self.token_cursor.break_last_token = false; + self.break_last_token = false; if next.0.span.is_dummy() { // Tweak the location for better diagnostics, but keep syntactic context intact. let fallback_span = self.token.span; -- cgit 1.4.1-3-g733a5 From ac64a53e17097f87de8913e372a0baa99e58e31e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 31 Jul 2023 16:57:35 +1000 Subject: Avoid an unnecessary local variable. --- compiler/rustc_parse/src/parser/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 27a8af630ce..f0d2411a7a6 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1241,8 +1241,7 @@ impl<'a> Parser<'a> { match self.token.kind { token::OpenDelim(..) => { // Grab the tokens within the delimiters. - let tree_cursor = &self.token_cursor.tree_cursor; - let stream = tree_cursor.stream.clone(); + let stream = self.token_cursor.tree_cursor.stream.clone(); let (_, delim, span) = *self.token_cursor.stack.last().unwrap(); // Advance the token cursor through the entire delimited -- cgit 1.4.1-3-g733a5 From d75ee2a6bcfc2ec9b21c0bb1ffaf34ff6b7161f1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Aug 2023 09:56:26 +1000 Subject: Remove `MacDelimiter`. It's the same as `Delimiter`, minus the `Invisible` variant. I'm generally in favour of using types to make impossible states unrepresentable, but this one feels very low-value, and the conversions between the two types are annoying and confusing. Look at the change in `src/tools/rustfmt/src/expr.rs` for an example: the old code converted from `MacDelimiter` to `Delimiter` and back again, for no good reason. This suggests the author was confused about the types. --- compiler/rustc_ast/src/ast.rs | 32 ++-------------------- compiler/rustc_ast/src/attr/mod.rs | 14 ++++------ compiler/rustc_ast_pretty/src/pprust/state.rs | 6 ++-- compiler/rustc_builtin_macros/src/assert.rs | 5 ++-- .../rustc_builtin_macros/src/assert/context.rs | 7 +++-- compiler/rustc_builtin_macros/src/edition_panic.rs | 3 +- compiler/rustc_expand/src/placeholders.rs | 3 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 4 +-- compiler/rustc_parse/src/parser/mod.rs | 6 ++-- compiler/rustc_parse/src/parser/stmt.rs | 3 +- compiler/rustc_parse/src/validate_attr.rs | 11 ++++---- src/tools/rustfmt/src/expr.rs | 8 ++---- 13 files changed, 37 insertions(+), 67 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index dd4321bea1b..2a268c2da85 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -14,7 +14,7 @@ //! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters. //! - [`EnumDef`] and [`Variant`]: Enum declaration. //! - [`MetaItemLit`] and [`LitKind`]: Literal expressions. -//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimiter`]: Macro definition and invocation. +//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`]: Macro definition and invocation. //! - [`Attribute`]: Metadata associated with item. //! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators. @@ -1693,7 +1693,7 @@ where #[derive(Clone, Encodable, Decodable, Debug)] pub struct DelimArgs { pub dspan: DelimSpan, - pub delim: MacDelimiter, + pub delim: Delimiter, // Note: `Delimiter::Invisible` never occurs pub tokens: TokenStream, } @@ -1701,7 +1701,7 @@ impl DelimArgs { /// 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, DelimArgs { delim: MacDelimiter::Brace, .. }) + !matches!(self, DelimArgs { delim: Delimiter::Brace, .. }) } } @@ -1717,32 +1717,6 @@ where } } -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] -pub enum MacDelimiter { - Parenthesis, - Bracket, - Brace, -} - -impl MacDelimiter { - pub fn to_token(self) -> Delimiter { - match self { - MacDelimiter::Parenthesis => Delimiter::Parenthesis, - MacDelimiter::Bracket => Delimiter::Bracket, - MacDelimiter::Brace => Delimiter::Brace, - } - } - - pub fn from_token(delim: Delimiter) -> Option { - match delim { - Delimiter::Parenthesis => Some(MacDelimiter::Parenthesis), - Delimiter::Bracket => Some(MacDelimiter::Bracket), - Delimiter::Brace => Some(MacDelimiter::Brace), - Delimiter::Invisible => None, - } - } -} - /// Represents a macro definition. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MacroDef { diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 8b9bb1df5dc..19a2b3017bc 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -2,7 +2,7 @@ use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute}; use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit}; -use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr}; +use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr}; use crate::ast::{Path, PathSegment, DUMMY_NODE_ID}; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter, Token}; @@ -196,7 +196,7 @@ impl AttrItem { fn meta_item_list(&self) -> Option> { match &self.args { - AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => { + AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => { MetaItemKind::list_from_tokens(args.tokens.clone()) } AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None, @@ -402,11 +402,9 @@ impl MetaItemKind { fn from_attr_args(args: &AttrArgs) -> Option { match args { AttrArgs::Empty => Some(MetaItemKind::Word), - AttrArgs::Delimited(DelimArgs { - dspan: _, - delim: MacDelimiter::Parenthesis, - tokens, - }) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List), + AttrArgs::Delimited(DelimArgs { dspan: _, delim: Delimiter::Parenthesis, tokens }) => { + MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List) + } AttrArgs::Delimited(..) => None, AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { ExprKind::Lit(token_lit) => { @@ -578,7 +576,7 @@ pub fn mk_attr_nested_word( let path = Path::from_ident(outer_ident); let attr_args = AttrArgs::Delimited(DelimArgs { dspan: DelimSpan::from_single(span), - delim: MacDelimiter::Parenthesis, + delim: Delimiter::Parenthesis, tokens: inner_tokens, }); mk_attr(g, style, path, attr_args, span) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 59239b49edd..068b255e9f2 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -476,7 +476,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Some(MacHeader::Path(&item.path)), false, None, - delim.to_token(), + *delim, tokens, true, span, @@ -640,7 +640,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Some(MacHeader::Keyword(kw)), has_bang, Some(*ident), - macro_def.body.delim.to_token(), + macro_def.body.delim, ¯o_def.body.tokens.clone(), true, sp, @@ -1240,7 +1240,7 @@ impl<'a> State<'a> { Some(MacHeader::Path(&m.path)), true, None, - m.args.delim.to_token(), + m.args.delim, &m.args.tokens.clone(), true, m.span(), diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index ab4ea9c8c20..3e90ae6907f 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -4,8 +4,9 @@ use crate::edition_panic::use_panic_2021; use crate::errors; use rustc_ast::ptr::P; use rustc_ast::token; +use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, MacDelimiter, Path, PathSegment, UnOp}; +use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp}; use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult}; @@ -58,7 +59,7 @@ pub fn expand_assert<'cx>( path: panic_path(), args: P(DelimArgs { dspan: DelimSpan::from_single(call_site_span), - delim: MacDelimiter::Parenthesis, + delim: Delimiter::Parenthesis, tokens, }), })), diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 902c1e40c75..cbf115127cf 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -1,9 +1,10 @@ use rustc_ast::{ ptr::P, token, + token::Delimiter, tokenstream::{DelimSpan, TokenStream, TokenTree}, - BinOpKind, BorrowKind, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MacDelimiter, MethodCall, - Mutability, Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID, + BinOpKind, BorrowKind, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MethodCall, Mutability, + Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -179,7 +180,7 @@ impl<'cx, 'a> Context<'cx, 'a> { path: panic_path, args: P(DelimArgs { dspan: DelimSpan::from_single(self.span), - delim: MacDelimiter::Parenthesis, + delim: Delimiter::Parenthesis, tokens: initial.into_iter().chain(captures).collect::(), }), })), diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index ef0db23ff2f..1e1dadab480 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -1,4 +1,5 @@ use rustc_ast::ptr::P; +use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::*; use rustc_expand::base::*; @@ -60,7 +61,7 @@ fn expand<'cx>( }, args: P(DelimArgs { dspan: DelimSpan::from_single(sp), - delim: MacDelimiter::Parenthesis, + delim: Delimiter::Parenthesis, tokens: tts, }), })), diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index e9af688ee2b..82cac229284 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -2,6 +2,7 @@ use crate::expand::{AstFragment, AstFragmentKind}; use rustc_ast as ast; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; +use rustc_ast::token::Delimiter; use rustc_data_structures::fx::FxHashMap; use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::Ident; @@ -18,7 +19,7 @@ pub fn placeholder( path: ast::Path { span: DUMMY_SP, segments: ThinVec::new(), tokens: None }, args: P(ast::DelimArgs { dspan: ast::tokenstream::DelimSpan::dummy(), - delim: ast::MacDelimiter::Parenthesis, + delim: Delimiter::Parenthesis, tokens: ast::tokenstream::TokenStream::new(Vec::new()), }), }) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 975dafecb10..dc3b131e7f2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2599,7 +2599,7 @@ impl<'a> Parser<'a> { // Recover from missing expression in `for` loop if matches!(expr.kind, ExprKind::Block(..)) - && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace)) + && !matches!(self.token.kind, token::OpenDelim(Delimiter::Brace)) && self.may_recover() { self.sess diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 1301ed3e388..e9cc858c8c5 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -9,12 +9,12 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; +use rustc_ast::MacCall; use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID}; use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::{BindingAnnotation, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, VariantData}; use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; -use rustc_ast::{MacCall, MacDelimiter}; use rustc_ast_pretty::pprust; use rustc_errors::{ struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult, @@ -1968,7 +1968,7 @@ impl<'a> Parser<'a> { let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); // `=>` let tokens = TokenStream::new(vec![params, arrow, body]); let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); - P(DelimArgs { dspan, delim: MacDelimiter::Brace, tokens }) + P(DelimArgs { dspan, delim: Delimiter::Brace, tokens }) } else { return self.unexpected(); }; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index f0d2411a7a6..c5b46b809b1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -25,7 +25,7 @@ use rustc_ast::util::case::Case; use rustc_ast::AttrId; use rustc_ast::DUMMY_NODE_ID; use rustc_ast::{self as ast, AnonConst, Const, DelimArgs, Extern}; -use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, MacDelimiter, Mutability, StrLit}; +use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, Mutability, StrLit}; use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; @@ -1216,12 +1216,10 @@ impl<'a> Parser<'a> { || self.check(&token::OpenDelim(Delimiter::Brace)); delimited.then(|| { - // We've confirmed above that there is a delimiter so unwrapping is OK. let TokenTree::Delimited(dspan, delim, tokens) = self.parse_token_tree() else { unreachable!() }; - - DelimArgs { dspan, delim: MacDelimiter::from_token(delim).unwrap(), tokens } + DelimArgs { dspan, delim, tokens } }) } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1cdf2efa764..12c267351b9 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -193,10 +193,9 @@ impl<'a> Parser<'a> { /// At this point, the `!` token after the path has already been eaten. fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResult<'a, Stmt> { let args = self.parse_delim_args()?; - let delim = args.delim.to_token(); let hi = self.prev_token.span; - let style = match delim { + let style = match args.delim { Delimiter::Brace => MacStmtStyle::Braces, _ => MacStmtStyle::NoBraces, }; diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 2011083019c..f7396598220 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -2,9 +2,10 @@ use crate::{errors, parse_in}; +use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::MetaItemKind; -use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MacDelimiter, MetaItem}; +use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem}; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; @@ -84,8 +85,8 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta }) } -pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter) { - if let ast::MacDelimiter::Parenthesis = delim { +pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: Delimiter) { + if let Delimiter::Parenthesis = delim { return; } sess.emit_err(errors::MetaBadDelim { @@ -94,8 +95,8 @@ pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimit }); } -pub fn check_cfg_attr_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter) { - if let ast::MacDelimiter::Parenthesis = delim { +pub fn check_cfg_attr_bad_delim(sess: &ParseSess, span: DelimSpan, delim: Delimiter) { + if let Delimiter::Parenthesis = delim { return; } sess.emit_err(errors::CfgAttrBadDelim { diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 5b1b4fbd491..739afb4e0ac 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -1382,12 +1382,8 @@ pub(crate) fn can_be_overflowed_expr( || (context.use_block_indent() && args_len == 1) } ast::ExprKind::MacCall(ref mac) => { - match ( - rustc_ast::ast::MacDelimiter::from_token(mac.args.delim.to_token()), - context.config.overflow_delimited_expr(), - ) { - (Some(ast::MacDelimiter::Bracket), true) - | (Some(ast::MacDelimiter::Brace), true) => true, + match (mac.args.delim, context.config.overflow_delimited_expr()) { + (Delimiter::Bracket, true) | (Delimiter::Brace, true) => true, _ => context.use_block_indent() && args_len == 1, } } -- cgit 1.4.1-3-g733a5 From bbd69e4a4c27f2407326a71a4eb37de694a72b87 Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Wed, 2 Aug 2023 23:59:30 +0000 Subject: Add test for enum with fields --- compiler/rustc_parse/src/parser/item.rs | 7 +-- tests/ui/parser/macro/macro-expand-to-field.rs | 57 +++++++++++++--------- tests/ui/parser/macro/macro-expand-to-field.stderr | 22 ++++++--- tests/ui/parser/macro/macro-expand-to-match-arm.rs | 5 +- 4 files changed, 54 insertions(+), 37 deletions(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 7b479067ecd..2f1d377585d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1754,12 +1754,7 @@ impl<'a> Parser<'a> { ident: None, vis, id: DUMMY_NODE_ID, - ty: P(Ty { - id: DUMMY_NODE_ID, - kind: TyKind::Err, - span: DUMMY_SP, - tokens: None, - }), + ty: self.mk_ty(DUMMY_SP, TyKind::Err), attrs, is_placeholder: false, }); diff --git a/tests/ui/parser/macro/macro-expand-to-field.rs b/tests/ui/parser/macro/macro-expand-to-field.rs index fd1d408e726..155872f7a5d 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.rs +++ b/tests/ui/parser/macro/macro-expand-to-field.rs @@ -1,4 +1,4 @@ -#![no_main] +// compile-flags: --crate-type=lib macro_rules! field { ($name:ident:$type:ty) => { @@ -13,9 +13,10 @@ macro_rules! variant { } struct Struct { - field!(bar:u128), //~ NOTE macros cannot expand to struct fields - //~^ ERROR unexpected token: `!` - //~^^ NOTE unexpected token after this + field!(bar:u128), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this a: u32, b: u32, field!(recovers:()), //~ NOTE macros cannot expand to struct fields @@ -24,34 +25,46 @@ struct Struct { } enum EnumVariant { - variant!(whoops), //~ NOTE macros cannot expand to enum variants - //~^ ERROR unexpected token: `!` - //~^^ NOTE unexpected token after this + variant!(whoops), + //~^ NOTE macros cannot expand to enum variants + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this U32, F64, - variant!(recovers), //~ NOTE macros cannot expand to enum variants - //~^ ERROR unexpected token: `!` - //~^^ NOTE unexpected token after this + variant!(recovers), + //~^ NOTE macros cannot expand to enum variants + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this + Data { + field!(x:u32), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| NOTE unexpected token after this + } } enum EnumVariantField { Named { - field!(oopsies:()), //~ NOTE macros cannot expand to struct fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this - field!(oopsies2:()), //~ NOTE macros cannot expand to struct fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this + field!(oopsies:()), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this + field!(oopsies2:()), + //~^ NOTE macros cannot expand to struct fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this }, } union Union { A: u32, - field!(oopsies:()), //~ NOTE macros cannot expand to union fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this + field!(oopsies:()), + //~^ NOTE macros cannot expand to union fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this B: u32, - field!(recovers:()), //~ NOTE macros cannot expand to union fields - //~^ ERROR unexpected token: `!` - //~^^ unexpected token after this + field!(recovers:()), + //~^ NOTE macros cannot expand to union fields + //~| ERROR unexpected token: `!` + //~| unexpected token after this } diff --git a/tests/ui/parser/macro/macro-expand-to-field.stderr b/tests/ui/parser/macro/macro-expand-to-field.stderr index 108b68b481f..adcd032f5c0 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.stderr +++ b/tests/ui/parser/macro/macro-expand-to-field.stderr @@ -7,7 +7,7 @@ LL | field!(bar:u128), = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:21:10 + --> $DIR/macro-expand-to-field.rs:22:10 | LL | field!(recovers:()), | ^ unexpected token after this @@ -15,7 +15,7 @@ LL | field!(recovers:()), = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:27:12 + --> $DIR/macro-expand-to-field.rs:28:12 | LL | variant!(whoops), | ^ unexpected token after this @@ -23,7 +23,7 @@ LL | variant!(whoops), = note: macros cannot expand to enum variants error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:32:12 + --> $DIR/macro-expand-to-field.rs:34:12 | LL | variant!(recovers), | ^ unexpected token after this @@ -33,13 +33,21 @@ LL | variant!(recovers), error: unexpected token: `!` --> $DIR/macro-expand-to-field.rs:39:14 | +LL | field!(x:u32), + | ^ unexpected token after this + | + = note: macros cannot expand to struct fields + +error: unexpected token: `!` + --> $DIR/macro-expand-to-field.rs:48:14 + | LL | field!(oopsies:()), | ^ unexpected token after this | = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:42:14 + --> $DIR/macro-expand-to-field.rs:52:14 | LL | field!(oopsies2:()), | ^ unexpected token after this @@ -47,7 +55,7 @@ LL | field!(oopsies2:()), = note: macros cannot expand to struct fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:50:10 + --> $DIR/macro-expand-to-field.rs:61:10 | LL | field!(oopsies:()), | ^ unexpected token after this @@ -55,12 +63,12 @@ LL | field!(oopsies:()), = note: macros cannot expand to union fields error: unexpected token: `!` - --> $DIR/macro-expand-to-field.rs:54:10 + --> $DIR/macro-expand-to-field.rs:66:10 | LL | field!(recovers:()), | ^ unexpected token after this | = note: macros cannot expand to union fields -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index c176e8bbd9d..39d1d065ed9 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -8,8 +8,9 @@ fn main() { let x = Some(1); match x { Some(1) => {}, - arm!(None => {}), //~ NOTE macros cannot expand to match arms - //~^ ERROR unexpected `,` in pattern + arm!(None => {}), + //~^ NOTE macros cannot expand to match arms + //~| ERROR unexpected `,` in pattern // doesn't recover Some(2) => {}, _ => {}, -- cgit 1.4.1-3-g733a5