Rollup merge of #57610 - mark-i-m:nested-matchers, r=petrochenkov
Fix nested `?` matchers fix #57597 I'm not 100% if this works yet... cc @alercah When this is ready (but perhaps not yet):
This commit is contained in:
commit
fd779d3f76
5 changed files with 253 additions and 24 deletions
|
@ -435,7 +435,8 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
|
||||||
match *seq_tt {
|
match *seq_tt {
|
||||||
TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
|
TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
|
||||||
TokenTree::Sequence(_, ref sub_seq) =>
|
TokenTree::Sequence(_, ref sub_seq) =>
|
||||||
sub_seq.op == quoted::KleeneOp::ZeroOrMore,
|
sub_seq.op == quoted::KleeneOp::ZeroOrMore
|
||||||
|
|| sub_seq.op == quoted::KleeneOp::ZeroOrOne,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
|
@ -543,7 +544,10 @@ impl FirstSets {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse scan: Sequence comes before `first`.
|
// Reverse scan: Sequence comes before `first`.
|
||||||
if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore {
|
if subfirst.maybe_empty
|
||||||
|
|| seq_rep.op == quoted::KleeneOp::ZeroOrMore
|
||||||
|
|| seq_rep.op == quoted::KleeneOp::ZeroOrOne
|
||||||
|
{
|
||||||
// If sequence is potentially empty, then
|
// If sequence is potentially empty, then
|
||||||
// union them (preserving first emptiness).
|
// union them (preserving first emptiness).
|
||||||
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
|
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
|
||||||
|
@ -591,8 +595,10 @@ impl FirstSets {
|
||||||
|
|
||||||
assert!(first.maybe_empty);
|
assert!(first.maybe_empty);
|
||||||
first.add_all(subfirst);
|
first.add_all(subfirst);
|
||||||
if subfirst.maybe_empty ||
|
if subfirst.maybe_empty
|
||||||
seq_rep.op == quoted::KleeneOp::ZeroOrMore {
|
|| seq_rep.op == quoted::KleeneOp::ZeroOrMore
|
||||||
|
|| seq_rep.op == quoted::KleeneOp::ZeroOrOne
|
||||||
|
{
|
||||||
// continue scanning for more first
|
// continue scanning for more first
|
||||||
// tokens, but also make sure we
|
// tokens, but also make sure we
|
||||||
// restore empty-tracking state
|
// restore empty-tracking state
|
||||||
|
|
|
@ -1,37 +1,59 @@
|
||||||
#![allow(unused_macros)]
|
#![allow(unused_macros)]
|
||||||
|
|
||||||
|
// Tests that repetition matchers cannot match the empty token tree (since that would be
|
||||||
|
// ambiguous).
|
||||||
|
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
macro_rules! foo {
|
macro_rules! foo {
|
||||||
( $()* ) => {};
|
( $()* ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
( $()+ ) => {};
|
( $()+ ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $()? ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
( $(),* ) => {}; // PASS
|
( $(),* ) => {}; // PASS
|
||||||
( $(),+ ) => {}; // PASS
|
( $(),+ ) => {}; // PASS
|
||||||
|
// `?` cannot have a separator...
|
||||||
( [$()*] ) => {};
|
( [$()*] ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
( [$()+] ) => {};
|
( [$()+] ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( [$()?] ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
( [$(),*] ) => {}; // PASS
|
( [$(),*] ) => {}; // PASS
|
||||||
( [$(),+] ) => {}; // PASS
|
( [$(),+] ) => {}; // PASS
|
||||||
|
// `?` cannot have a separator...
|
||||||
( $($()* $(),* $(a)* $(a),* )* ) => {};
|
( $($()* $(),* $(a)* $(a),* )* ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
( $($()* $(),* $(a)* $(a),* )+ ) => {};
|
( $($()* $(),* $(a)* $(a),* )+ ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $($()* $(),* $(a)* $(a),* )? ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $($()? $(),* $(a)? $(a),* )* ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $($()? $(),* $(a)? $(a),* )+ ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $($()? $(),* $(a)? $(a),* )? ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS
|
( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS
|
||||||
( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS
|
( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS
|
||||||
|
( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS
|
||||||
|
|
||||||
|
( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS
|
||||||
|
( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS
|
||||||
|
( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS
|
||||||
|
|
||||||
( $(a $()+)* ) => {};
|
( $(a $()+)* ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
( $(a $()*)+ ) => {};
|
( $(a $()*)+ ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $(a $()+)? ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
( $(a $()?)+ ) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Original Issue --- //
|
// --- Original Issue --- //
|
||||||
|
|
||||||
macro_rules! make_vec {
|
macro_rules! make_vec {
|
||||||
|
@ -43,11 +65,10 @@ fn main() {
|
||||||
let _ = make_vec![a 1, a 2, a 3];
|
let _ = make_vec![a 1, a 2, a 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Minified Issue --- //
|
// --- Minified Issue --- //
|
||||||
|
|
||||||
macro_rules! m {
|
macro_rules! m {
|
||||||
( $()* ) => {}
|
( $()* ) => {};
|
||||||
//~^ ERROR repetition matches empty token tree
|
//~^ ERROR repetition matches empty token tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,62 +1,110 @@
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:4:8
|
--> $DIR/issue-5067.rs:9:8
|
||||||
|
|
|
|
||||||
LL | ( $()* ) => {};
|
LL | ( $()* ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:6:8
|
--> $DIR/issue-5067.rs:11:8
|
||||||
|
|
|
|
||||||
LL | ( $()+ ) => {};
|
LL | ( $()+ ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:12:9
|
--> $DIR/issue-5067.rs:13:8
|
||||||
|
|
|
||||||
|
LL | ( $()? ) => {};
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:18:9
|
||||||
|
|
|
|
||||||
LL | ( [$()*] ) => {};
|
LL | ( [$()*] ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:14:9
|
--> $DIR/issue-5067.rs:20:9
|
||||||
|
|
|
|
||||||
LL | ( [$()+] ) => {};
|
LL | ( [$()+] ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:20:8
|
--> $DIR/issue-5067.rs:22:9
|
||||||
|
|
|
||||||
|
LL | ( [$()?] ) => {};
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:27:8
|
||||||
|
|
|
|
||||||
LL | ( $($()* $(),* $(a)* $(a),* )* ) => {};
|
LL | ( $($()* $(),* $(a)* $(a),* )* ) => {};
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:22:8
|
--> $DIR/issue-5067.rs:29:8
|
||||||
|
|
|
|
||||||
LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {};
|
LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {};
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:28:12
|
--> $DIR/issue-5067.rs:31:8
|
||||||
|
|
|
||||||
|
LL | ( $($()* $(),* $(a)* $(a),* )? ) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:33:8
|
||||||
|
|
|
||||||
|
LL | ( $($()? $(),* $(a)? $(a),* )* ) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:35:8
|
||||||
|
|
|
||||||
|
LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:37:8
|
||||||
|
|
|
||||||
|
LL | ( $($()? $(),* $(a)? $(a),* )? ) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:47:12
|
||||||
|
|
|
|
||||||
LL | ( $(a $()+)* ) => {};
|
LL | ( $(a $()+)* ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:30:12
|
--> $DIR/issue-5067.rs:49:12
|
||||||
|
|
|
|
||||||
LL | ( $(a $()*)+ ) => {};
|
LL | ( $(a $()*)+ ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:38:18
|
--> $DIR/issue-5067.rs:51:12
|
||||||
|
|
|
||||||
|
LL | ( $(a $()+)? ) => {};
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:53:12
|
||||||
|
|
|
||||||
|
LL | ( $(a $()?)+ ) => {};
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-5067.rs:60:18
|
||||||
|
|
|
|
||||||
LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
|
LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: repetition matches empty token tree
|
error: repetition matches empty token tree
|
||||||
--> $DIR/issue-5067.rs:50:8
|
--> $DIR/issue-5067.rs:71:8
|
||||||
|
|
|
|
||||||
LL | ( $()* ) => {}
|
LL | ( $()* ) => {};
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 18 previous errors
|
||||||
|
|
||||||
|
|
80
src/test/ui/issues/issue-57597.rs
Normal file
80
src/test/ui/issues/issue-57597.rs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// Regression test for #57597.
|
||||||
|
//
|
||||||
|
// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
|
||||||
|
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
macro_rules! foo1 {
|
||||||
|
($($($i:ident)?)+) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo2 {
|
||||||
|
($($($i:ident)?)*) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo3 {
|
||||||
|
($($($i:ident)?)?) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo4 {
|
||||||
|
($($($($i:ident)?)?)?) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo5 {
|
||||||
|
($($($($i:ident)*)?)?) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo6 {
|
||||||
|
($($($($i:ident)?)*)?) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo7 {
|
||||||
|
($($($($i:ident)?)?)*) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo8 {
|
||||||
|
($($($($i:ident)*)*)?) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo9 {
|
||||||
|
($($($($i:ident)?)*)*) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo10 {
|
||||||
|
($($($($i:ident)?)*)+) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo11 {
|
||||||
|
($($($($i:ident)+)?)*) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! foo12 {
|
||||||
|
($($($($i:ident)+)*)?) => {};
|
||||||
|
//~^ ERROR repetition matches empty token tree
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo1!();
|
||||||
|
foo2!();
|
||||||
|
foo3!();
|
||||||
|
foo4!();
|
||||||
|
foo5!();
|
||||||
|
foo6!();
|
||||||
|
foo7!();
|
||||||
|
foo8!();
|
||||||
|
foo9!();
|
||||||
|
foo10!();
|
||||||
|
foo11!();
|
||||||
|
foo12!();
|
||||||
|
}
|
74
src/test/ui/issues/issue-57597.stderr
Normal file
74
src/test/ui/issues/issue-57597.stderr
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:8:7
|
||||||
|
|
|
||||||
|
LL | ($($($i:ident)?)+) => {};
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:13:7
|
||||||
|
|
|
||||||
|
LL | ($($($i:ident)?)*) => {};
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:18:7
|
||||||
|
|
|
||||||
|
LL | ($($($i:ident)?)?) => {};
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:23:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)?)?)?) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:28:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)*)?)?) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:33:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)?)*)?) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:38:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)?)?)*) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:43:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)*)*)?) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:48:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)?)*)*) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:53:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)?)*)+) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:58:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)+)?)*) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: repetition matches empty token tree
|
||||||
|
--> $DIR/issue-57597.rs:63:7
|
||||||
|
|
|
||||||
|
LL | ($($($($i:ident)+)*)?) => {};
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 12 previous errors
|
||||||
|
|
Loading…
Reference in a new issue