diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 707fb65bcc52b..b52e3b7150567 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -1,5 +1,4 @@ use crate::ast::NodeId; -use crate::early_buffered_lints::BufferedEarlyLintId; use crate::ext::tt::macro_parser; use crate::feature_gate::Features; use crate::parse::token::{self, Token, TokenKind}; @@ -250,19 +249,16 @@ pub fn parse( /// - `sess`: the parsing session. Any errors will be emitted to this session. /// - `features`, `attrs`: language feature flags and attributes so that we know whether to use /// unstable features or not. -fn parse_tree( +fn parse_tree( tree: tokenstream::TokenTree, - trees: &mut Peekable, + trees: &mut Peekable>, expect_matchers: bool, sess: &ParseSess, features: &Features, attrs: &[ast::Attribute], edition: Edition, macro_node_id: NodeId, -) -> TokenTree -where - I: Iterator, -{ +) -> TokenTree { // Depending on what `tree` is, we could be parsing different parts of a macro match tree { // `tree` is a `$` token. Look at the next token in `trees` @@ -287,16 +283,7 @@ where macro_node_id, ); // Get the Kleene operator and optional separator - let (separator, op) = - parse_sep_and_kleene_op( - trees, - span.entire(), - sess, - features, - attrs, - edition, - macro_node_id, - ); + let (separator, op) = parse_sep_and_kleene_op(trees, span.entire(), sess); // Count the number of captured "names" (i.e., named metavars) let name_captures = macro_parser::count_names(&sequence); TokenTree::Sequence( @@ -375,10 +362,10 @@ fn kleene_op(token: &Token) -> Option { /// - Ok(Ok((op, span))) if the next token tree is a KleeneOp /// - Ok(Err(tok, span)) if the next token tree is a token but not a KleeneOp /// - Err(span) if the next token tree is not a token -fn parse_kleene_op(input: &mut I, span: Span) -> Result, Span> -where - I: Iterator, -{ +fn parse_kleene_op( + input: &mut impl Iterator, + span: Span, +) -> Result, Span> { match input.next() { Some(tokenstream::TokenTree::Token(token)) => match kleene_op(&token) { Some(op) => Ok(Ok((op, token.span))), @@ -403,178 +390,20 @@ where /// session `sess`. If the next one (or possibly two) tokens in `input` correspond to a Kleene /// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an /// error with the appropriate span is emitted to `sess` and a dummy value is returned. -/// -/// N.B., in the 2015 edition, `*` and `+` are the only Kleene operators, and `?` is a separator. -/// In the 2018 edition however, `?` is a Kleene operator, and not a separator. -fn parse_sep_and_kleene_op( - input: &mut Peekable, - span: Span, - sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, -) -> (Option, KleeneOp) -where - I: Iterator, -{ - match edition { - Edition::Edition2015 => parse_sep_and_kleene_op_2015( - input, - span, - sess, - features, - attrs, - macro_node_id, - ), - Edition::Edition2018 => parse_sep_and_kleene_op_2018(input, span, sess, features, attrs), - } -} - -// `?` is a separator (with a migration warning) and never a KleeneOp. -fn parse_sep_and_kleene_op_2015( - input: &mut Peekable, - span: Span, - sess: &ParseSess, - _features: &Features, - _attrs: &[ast::Attribute], - macro_node_id: NodeId, -) -> (Option, KleeneOp) -where - I: Iterator, -{ - // We basically look at two token trees here, denoted as #1 and #2 below - let span = match parse_kleene_op(input, span) { - // #1 is a `+` or `*` KleeneOp - // - // `?` is ambiguous: it could be a separator (warning) or a Kleene::ZeroOrOne (error), so - // we need to look ahead one more token to be sure. - Ok(Ok((op, _))) if op != KleeneOp::ZeroOrOne => return (None, op), - - // #1 is `?` token, but it could be a Kleene::ZeroOrOne (error in 2015) without a separator - // or it could be a `?` separator followed by any Kleene operator. We need to look ahead 1 - // token to find out which. - Ok(Ok((op, op1_span))) => { - assert_eq!(op, KleeneOp::ZeroOrOne); - - // Lookahead at #2. If it is a KleenOp, then #1 is a separator. - let is_1_sep = if let Some(tokenstream::TokenTree::Token(tok2)) = input.peek() { - kleene_op(tok2).is_some() - } else { - false - }; - - if is_1_sep { - // #1 is a separator and #2 should be a KleepeOp. - // (N.B. We need to advance the input iterator.) - match parse_kleene_op(input, span) { - // #2 is `?`, which is not allowed as a Kleene op in 2015 edition, - // but is allowed in the 2018 edition. - Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => { - sess.span_diagnostic - .struct_span_err(op2_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator in the 2015 edition, \ - but is accepted in the 2018 edition") - .emit(); - - // Return a dummy - return (None, KleeneOp::ZeroOrMore); - } - - // #2 is a Kleene op, which is the only valid option - Ok(Ok((op, _))) => { - // Warn that `?` as a separator will be deprecated - sess.buffer_lint( - BufferedEarlyLintId::QuestionMarkMacroSep, - op1_span, - macro_node_id, - "using `?` as a separator is deprecated and will be \ - a hard error in an upcoming edition", - ); - - return (Some(Token::new(token::Question, op1_span)), op); - } - - // #2 is a random token (this is an error) :( - Ok(Err(_)) => op1_span, - - // #2 is not even a token at all :( - Err(_) => op1_span, - } - } else { - // `?` is not allowed as a Kleene op in 2015, - // but is allowed in the 2018 edition - sess.span_diagnostic - .struct_span_err(op1_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator in the 2015 edition, \ - but is accepted in the 2018 edition") - .emit(); - - // Return a dummy - return (None, KleeneOp::ZeroOrMore); - } - } - - // #1 is a separator followed by #2, a KleeneOp - Ok(Err(token)) => match parse_kleene_op(input, token.span) { - // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition, - // but is allowed in the 2018 edition - Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => { - sess.span_diagnostic - .struct_span_err(op2_span, "expected `*` or `+`") - .note("`?` is not a macro repetition operator in the 2015 edition, \ - but is accepted in the 2018 edition") - .emit(); - - // Return a dummy - return (None, KleeneOp::ZeroOrMore); - } - - // #2 is a KleeneOp :D - Ok(Ok((op, _))) => return (Some(token), op), - - // #2 is a random token :( - Ok(Err(token)) => token.span, - - // #2 is not a token at all :( - Err(span) => span, - }, - - // #1 is not a token - Err(span) => span, - }; - - sess.span_diagnostic.span_err(span, "expected `*` or `+`"); - - // Return a dummy - (None, KleeneOp::ZeroOrMore) -} - -// `?` is a Kleene op, not a separator -fn parse_sep_and_kleene_op_2018( - input: &mut Peekable, +fn parse_sep_and_kleene_op( + input: &mut Peekable>, span: Span, sess: &ParseSess, - _features: &Features, - _attrs: &[ast::Attribute], -) -> (Option, KleeneOp) -where - I: Iterator, -{ +) -> (Option, KleeneOp) { // We basically look at two token trees here, denoted as #1 and #2 below let span = match parse_kleene_op(input, span) { - // #1 is a `?` (needs feature gate) - Ok(Ok((op, _op1_span))) if op == KleeneOp::ZeroOrOne => { - return (None, op); - } - - // #1 is a `+` or `*` KleeneOp + // #1 is a `?`, `+`, or `*` KleeneOp Ok(Ok((op, _))) => return (None, op), // #1 is a separator followed by #2, a KleeneOp Ok(Err(token)) => match parse_kleene_op(input, token.span) { // #2 is the `?` Kleene op, which does not take a separator (error) - Ok(Ok((op, _op2_span))) if op == KleeneOp::ZeroOrOne => { + Ok(Ok((KleeneOp::ZeroOrOne, _))) => { // Error! sess.span_diagnostic.span_err( token.span, @@ -588,11 +417,8 @@ where // #2 is a KleeneOp :D Ok(Ok((op, _))) => return (Some(token), op), - // #2 is a random token :( - Ok(Err(token)) => token.span, - - // #2 is not a token at all :( - Err(span) => span, + // #2 is a random token or not a token at all :( + Ok(Err(Token { span, .. })) | Err(span) => span, }, // #1 is not a token diff --git a/src/test/run-pass/macros/macro-at-most-once-rep-2015.rs b/src/test/run-pass/macros/macro-at-most-once-rep-2015.rs new file mode 100644 index 0000000000000..66597c0acf628 --- /dev/null +++ b/src/test/run-pass/macros/macro-at-most-once-rep-2015.rs @@ -0,0 +1,50 @@ +// run-pass + +#![allow(unused_mut)] + +// Check that when `?` is followed by what looks like a Kleene operator (?, +, and *) +// then that `?` is not interpreted as a separator. In other words, `$(pat)?+` matches `pat +` +// or `+` but does not match `pat` or `pat ? pat`. + +// edition:2015 + +macro_rules! foo { + // Check for `?`. + ($($a:ident)? ? $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `+`. + ($($a:ident)? + $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `*`. + ($($a:ident)? * $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `;`, not a kleene operator. + ($($a:ident)? ; $num:expr) => { + let mut x = 0; + + $( + x += $a; + )? + + assert_eq!(x, $num); + }; +} + +pub fn main() { + let a = 1; + + // Accept 0 repetitions. + foo!( ; 0); + foo!( + 0); + foo!( * 0); + foo!( ? 0); + + // Accept 1 repetition. + foo!(a ; 1); + foo!(a + 1); + foo!(a * 1); + foo!(a ? 1); +} diff --git a/src/test/run-pass/macros/macro-at-most-once-rep-2018.rs b/src/test/run-pass/macros/macro-at-most-once-rep-2018.rs new file mode 100644 index 0000000000000..b37f3853016a6 --- /dev/null +++ b/src/test/run-pass/macros/macro-at-most-once-rep-2018.rs @@ -0,0 +1,50 @@ +// run-pass + +#![allow(unused_mut)] + +// Check that when `?` is followed by what looks like a Kleene operator (?, +, and *) +// then that `?` is not interpreted as a separator. In other words, `$(pat)?+` matches `pat +` +// or `+` but does not match `pat` or `pat ? pat`. + +// edition:2018 + +macro_rules! foo { + // Check for `?`. + ($($a:ident)? ? $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `+`. + ($($a:ident)? + $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `*`. + ($($a:ident)? * $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `;`, not a kleene operator. + ($($a:ident)? ; $num:expr) => { + let mut x = 0; + + $( + x += $a; + )? + + assert_eq!(x, $num); + }; +} + +pub fn main() { + let a = 1; + + // Accept 0 repetitions. + foo!( ; 0); + foo!( + 0); + foo!( * 0); + foo!( ? 0); + + // Accept 1 repetition. + foo!(a ; 1); + foo!(a + 1); + foo!(a * 1); + foo!(a ? 1); +} diff --git a/src/test/run-pass/macros/macro-at-most-once-rep.rs b/src/test/run-pass/macros/macro-at-most-once-rep.rs deleted file mode 100644 index 582ef088a73c9..0000000000000 --- a/src/test/run-pass/macros/macro-at-most-once-rep.rs +++ /dev/null @@ -1,33 +0,0 @@ -// run-pass -#![allow(unused_mut)] -// The logic for parsing Kleene operators in macros has a special case to disambiguate `?`. -// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the -// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to -// exercise that logic in the macro parser. -// -// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but -// included for consistency with `+` and `*`. -// -// This test focuses on non-error cases and making sure the correct number of repetitions happen. - -// edition:2018 - -macro_rules! foo { - ($($a:ident)? ; $num:expr) => { { - let mut x = 0; - - $( - x += $a; - )? - - assert_eq!(x, $num); - } } -} - -pub fn main() { - let a = 1; - - // accept 0 or 1 repetitions - foo!( ; 0); - foo!(a ; 1); -} diff --git a/src/test/ui/issues/issue-39388.rs b/src/test/ui/issues/issue-39388.rs index e5b1cd93614bb..a8e31a648c9ed 100644 --- a/src/test/ui/issues/issue-39388.rs +++ b/src/test/ui/issues/issue-39388.rs @@ -1,7 +1,7 @@ #![allow(unused_macros)] macro_rules! assign { - (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+` + (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?` $($a)* = $($b)* } } diff --git a/src/test/ui/issues/issue-39388.stderr b/src/test/ui/issues/issue-39388.stderr index e04e16e2a0375..62e7dff547692 100644 --- a/src/test/ui/issues/issue-39388.stderr +++ b/src/test/ui/issues/issue-39388.stderr @@ -1,4 +1,4 @@ -error: expected `*` or `+` +error: expected one of: `*`, `+`, or `?` --> $DIR/issue-39388.rs:4:22 | LL | (($($a:tt)*) = ($($b:tt))*) => { diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs deleted file mode 100644 index 2d8d2ecf9d7b4..0000000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Test behavior of `?` macro _kleene op_ under the 2015 edition. Namely, it doesn't exist. - -// edition:2015 - -macro_rules! bar { - ($(a)?) => {} //~ERROR expected `*` or `+` -} - -macro_rules! baz { - ($(a),?) => {} //~ERROR expected `*` or `+` -} - -fn main() {} diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr deleted file mode 100644 index e78f2833078cc..0000000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:6:10 - | -LL | ($(a)?) => {} - | ^ - | - = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition - -error: expected `*` or `+` - --> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:10:11 - | -LL | ($(a),?) => {} - | ^ - | - = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs deleted file mode 100644 index c8c920ff3f87a..0000000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Test behavior of `?` macro _separator_ under the 2015 edition. Namely, `?` can be used as a -// separator, but you get a migration warning for the edition. - -// edition:2015 -// compile-pass - -#![warn(rust_2018_compatibility)] - -macro_rules! bar { - ($(a)?*) => {} //~WARN using `?` as a separator - //~^WARN this was previously accepted -} - -macro_rules! baz { - ($(a)?+) => {} //~WARN using `?` as a separator - //~^WARN this was previously accepted -} - -fn main() { - bar!(); - bar!(a); - bar!(a?a); - bar!(a?a?a?a?a); - - baz!(a); - baz!(a?a); - baz!(a?a?a?a?a); -} diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr deleted file mode 100644 index bf1861ae54052..0000000000000 --- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-sep.stderr +++ /dev/null @@ -1,24 +0,0 @@ -warning: using `?` as a separator is deprecated and will be a hard error in an upcoming edition - --> $DIR/macro-at-most-once-rep-2015-ques-sep.rs:10:10 - | -LL | ($(a)?*) => {} - | ^ - | -note: lint level defined here - --> $DIR/macro-at-most-once-rep-2015-ques-sep.rs:7:9 - | -LL | #![warn(rust_2018_compatibility)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - = note: #[warn(question_mark_macro_sep)] implied by #[warn(rust_2018_compatibility)] - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! - = note: for more information, see issue #48075 - -warning: using `?` as a separator is deprecated and will be a hard error in an upcoming edition - --> $DIR/macro-at-most-once-rep-2015-ques-sep.rs:15:10 - | -LL | ($(a)?+) => {} - | ^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! - = note: for more information, see issue #48075 - diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015.rs b/src/test/ui/macros/macro-at-most-once-rep-2015.rs new file mode 100644 index 0000000000000..f68100d4557d6 --- /dev/null +++ b/src/test/ui/macros/macro-at-most-once-rep-2015.rs @@ -0,0 +1,42 @@ +// Tests that `?` is a Kleene op and not a macro separator in the 2015 edition. + +// edition:2015 + +macro_rules! foo { + ($(a)?) => {}; +} + +// The Kleene op `?` does not admit a separator before it. +macro_rules! baz { + ($(a),?) => {}; //~ERROR the `?` macro repetition operator +} + +macro_rules! barplus { + ($(a)?+) => {}; // ok. matches "a+" and "+" +} + +macro_rules! barstar { + ($(a)?*) => {}; // ok. matches "a*" and "*" +} + +pub fn main() { + foo!(); + foo!(a); + foo!(a?); //~ ERROR no rules expected the token `?` + foo!(a?a); //~ ERROR no rules expected the token `?` + foo!(a?a?a); //~ ERROR no rules expected the token `?` + + barplus!(); //~ERROR unexpected end of macro invocation + barplus!(a); //~ERROR unexpected end of macro invocation + barplus!(a?); //~ ERROR no rules expected the token `?` + barplus!(a?a); //~ ERROR no rules expected the token `?` + barplus!(a+); + barplus!(+); + + barstar!(); //~ERROR unexpected end of macro invocation + barstar!(a); //~ERROR unexpected end of macro invocation + barstar!(a?); //~ ERROR no rules expected the token `?` + barstar!(a?a); //~ ERROR no rules expected the token `?` + barstar!(a*); + barstar!(*); +} diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015.stderr new file mode 100644 index 0000000000000..f9871ab8ffe0c --- /dev/null +++ b/src/test/ui/macros/macro-at-most-once-rep-2015.stderr @@ -0,0 +1,107 @@ +error: the `?` macro repetition operator does not take a separator + --> $DIR/macro-at-most-once-rep-2015.rs:11:10 + | +LL | ($(a),?) => {}; + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:25:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?); + | ^ no rules expected this token in macro call + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:26:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?a); + | ^ no rules expected this token in macro call + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:27:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?a?a); + | ^ no rules expected this token in macro call + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:29:5 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(); + | ^^^^^^^^^^^ missing tokens in macro arguments + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:30:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a); + | ^ missing tokens in macro arguments + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:31:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a?); + | ^ no rules expected this token in macro call + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:32:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a?a); + | ^ no rules expected this token in macro call + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:36:5 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(); + | ^^^^^^^^^^^ missing tokens in macro arguments + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:37:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a); + | ^ missing tokens in macro arguments + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:38:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a?); + | ^ no rules expected this token in macro call + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:39:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a?a); + | ^ no rules expected this token in macro call + +error: aborting due to 12 previous errors + diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs index da072adec1516..886a25bbcbcb2 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.rs +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs @@ -6,6 +6,7 @@ macro_rules! foo { ($(a)?) => {}; } +// The Kleene op `?` does not admit a separator before it. macro_rules! baz { ($(a),?) => {}; //~ERROR the `?` macro repetition operator } diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index f285c7cc7c279..bfe5883b03fa0 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -1,11 +1,11 @@ error: the `?` macro repetition operator does not take a separator - --> $DIR/macro-at-most-once-rep-2018.rs:10:10 + --> $DIR/macro-at-most-once-rep-2018.rs:11:10 | LL | ($(a),?) => {}; | ^ error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:24:11 + --> $DIR/macro-at-most-once-rep-2018.rs:25:11 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -14,7 +14,7 @@ LL | foo!(a?); | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:25:11 + --> $DIR/macro-at-most-once-rep-2018.rs:26:11 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -23,7 +23,7 @@ LL | foo!(a?a); | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:26:11 + --> $DIR/macro-at-most-once-rep-2018.rs:27:11 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -32,7 +32,7 @@ LL | foo!(a?a?a); | ^ no rules expected this token in macro call error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:28:5 + --> $DIR/macro-at-most-once-rep-2018.rs:29:5 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -41,7 +41,7 @@ LL | barplus!(); | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:29:15 + --> $DIR/macro-at-most-once-rep-2018.rs:30:15 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -50,7 +50,7 @@ LL | barplus!(a); | ^ missing tokens in macro arguments error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:30:15 + --> $DIR/macro-at-most-once-rep-2018.rs:31:15 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -59,7 +59,7 @@ LL | barplus!(a?); | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:31:15 + --> $DIR/macro-at-most-once-rep-2018.rs:32:15 | LL | macro_rules! barplus { | -------------------- when calling this macro @@ -68,7 +68,7 @@ LL | barplus!(a?a); | ^ no rules expected this token in macro call error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:35:5 + --> $DIR/macro-at-most-once-rep-2018.rs:36:5 | LL | macro_rules! barstar { | -------------------- when calling this macro @@ -77,7 +77,7 @@ LL | barstar!(); | ^^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation - --> $DIR/macro-at-most-once-rep-2018.rs:36:15 + --> $DIR/macro-at-most-once-rep-2018.rs:37:15 | LL | macro_rules! barstar { | -------------------- when calling this macro @@ -86,7 +86,7 @@ LL | barstar!(a); | ^ missing tokens in macro arguments error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:37:15 + --> $DIR/macro-at-most-once-rep-2018.rs:38:15 | LL | macro_rules! barstar { | -------------------- when calling this macro @@ -95,7 +95,7 @@ LL | barstar!(a?); | ^ no rules expected this token in macro call error: no rules expected the token `?` - --> $DIR/macro-at-most-once-rep-2018.rs:38:15 + --> $DIR/macro-at-most-once-rep-2018.rs:39:15 | LL | macro_rules! barstar { | -------------------- when calling this macro diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs index 83f8a562a03ad..9ed53519ceb31 100644 --- a/src/test/ui/parser/macro/issue-33569.rs +++ b/src/test/ui/parser/macro/issue-33569.rs @@ -1,7 +1,7 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` //~^ ERROR missing fragment specifier - $(x)(y) //~ ERROR expected `*` or `+` + $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` } } diff --git a/src/test/ui/parser/macro/issue-33569.stderr b/src/test/ui/parser/macro/issue-33569.stderr index 8ba72fc88862a..b4d38d3ce4806 100644 --- a/src/test/ui/parser/macro/issue-33569.stderr +++ b/src/test/ui/parser/macro/issue-33569.stderr @@ -4,7 +4,7 @@ error: expected identifier, found `+` LL | { $+ } => { | ^ -error: expected `*` or `+` +error: expected one of: `*`, `+`, or `?` --> $DIR/issue-33569.rs:4:13 | LL | $(x)(y)