Auto merge of #60932 - Centril:macro-at-most-once-2015, r=mark-i-m
Support ? Kleene macro operator in 2015 Closes https://github.com/rust-lang/rust/issues/56668. See that issue for rationale and discussion. Crater will be needed (done in https://github.com/rust-lang/rust/pull/60932#issuecomment-494188577, zero regressions) and then, if all goes well, FCP (in https://github.com/rust-lang/rust/pull/60932#issuecomment-494189802).
This commit is contained in:
commit
e6e60ef6ea
16 changed files with 281 additions and 321 deletions
|
@ -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<I>(
|
||||
fn parse_tree(
|
||||
tree: tokenstream::TokenTree,
|
||||
trees: &mut Peekable<I>,
|
||||
trees: &mut Peekable<impl Iterator<Item = tokenstream::TokenTree>>,
|
||||
expect_matchers: bool,
|
||||
sess: &ParseSess,
|
||||
features: &Features,
|
||||
attrs: &[ast::Attribute],
|
||||
edition: Edition,
|
||||
macro_node_id: NodeId,
|
||||
) -> TokenTree
|
||||
where
|
||||
I: Iterator<Item = tokenstream::TokenTree>,
|
||||
{
|
||||
) -> 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<KleeneOp> {
|
|||
/// - 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<I>(input: &mut I, span: Span) -> Result<Result<(KleeneOp, Span), Token>, Span>
|
||||
where
|
||||
I: Iterator<Item = tokenstream::TokenTree>,
|
||||
{
|
||||
fn parse_kleene_op(
|
||||
input: &mut impl Iterator<Item = tokenstream::TokenTree>,
|
||||
span: Span,
|
||||
) -> Result<Result<(KleeneOp, Span), Token>, 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<I>(
|
||||
input: &mut Peekable<I>,
|
||||
fn parse_sep_and_kleene_op(
|
||||
input: &mut Peekable<impl Iterator<Item = tokenstream::TokenTree>>,
|
||||
span: Span,
|
||||
sess: &ParseSess,
|
||||
features: &Features,
|
||||
attrs: &[ast::Attribute],
|
||||
edition: Edition,
|
||||
macro_node_id: NodeId,
|
||||
) -> (Option<Token>, KleeneOp)
|
||||
where
|
||||
I: Iterator<Item = tokenstream::TokenTree>,
|
||||
{
|
||||
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<I>(
|
||||
input: &mut Peekable<I>,
|
||||
span: Span,
|
||||
sess: &ParseSess,
|
||||
_features: &Features,
|
||||
_attrs: &[ast::Attribute],
|
||||
macro_node_id: NodeId,
|
||||
) -> (Option<Token>, KleeneOp)
|
||||
where
|
||||
I: Iterator<Item = tokenstream::TokenTree>,
|
||||
{
|
||||
) -> (Option<Token>, 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 `+` 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<I>(
|
||||
input: &mut Peekable<I>,
|
||||
span: Span,
|
||||
sess: &ParseSess,
|
||||
_features: &Features,
|
||||
_attrs: &[ast::Attribute],
|
||||
) -> (Option<Token>, KleeneOp)
|
||||
where
|
||||
I: Iterator<Item = tokenstream::TokenTree>,
|
||||
{
|
||||
// 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
|
||||
|
|
50
src/test/run-pass/macros/macro-at-most-once-rep-2015.rs
Normal file
50
src/test/run-pass/macros/macro-at-most-once-rep-2015.rs
Normal file
|
@ -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);
|
||||
}
|
50
src/test/run-pass/macros/macro-at-most-once-rep-2018.rs
Normal file
50
src/test/run-pass/macros/macro-at-most-once-rep-2018.rs
Normal file
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)*
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: expected `*` or `+`
|
||||
error: expected one of: `*`, `+`, or `?`
|
||||
--> $DIR/issue-39388.rs:4:22
|
||||
|
|
||||
LL | (($($a:tt)*) = ($($b:tt))*) => {
|
||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/48075>
|
||||
|
42
src/test/ui/macros/macro-at-most-once-rep-2015.rs
Normal file
42
src/test/ui/macros/macro-at-most-once-rep-2015.rs
Normal file
|
@ -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!(*);
|
||||
}
|
107
src/test/ui/macros/macro-at-most-once-rep-2015.stderr
Normal file
107
src/test/ui/macros/macro-at-most-once-rep-2015.stderr
Normal file
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 `?`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue