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 {
|
||||
TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
|
||||
TokenTree::Sequence(_, ref sub_seq) =>
|
||||
sub_seq.op == quoted::KleeneOp::ZeroOrMore,
|
||||
sub_seq.op == quoted::KleeneOp::ZeroOrMore
|
||||
|| sub_seq.op == quoted::KleeneOp::ZeroOrOne,
|
||||
_ => false,
|
||||
}
|
||||
}) {
|
||||
|
@ -543,7 +544,10 @@ impl FirstSets {
|
|||
}
|
||||
|
||||
// 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
|
||||
// union them (preserving first emptiness).
|
||||
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
|
||||
|
@ -591,8 +595,10 @@ impl FirstSets {
|
|||
|
||||
assert!(first.maybe_empty);
|
||||
first.add_all(subfirst);
|
||||
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
|
||||
{
|
||||
// continue scanning for more first
|
||||
// tokens, but also make sure we
|
||||
// restore empty-tracking state
|
||||
|
|
|
@ -1,37 +1,59 @@
|
|||
#![allow(unused_macros)]
|
||||
|
||||
// Tests that repetition matchers cannot match the empty token tree (since that would be
|
||||
// ambiguous).
|
||||
|
||||
// edition:2018
|
||||
|
||||
macro_rules! foo {
|
||||
( $()* ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( $()+ ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
|
||||
( $()? ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( $(),* ) => {}; // PASS
|
||||
( $(),+ ) => {}; // PASS
|
||||
|
||||
// `?` cannot have a separator...
|
||||
( [$()*] ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( [$()+] ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
|
||||
( [$()?] ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( [$(),*] ) => {}; // PASS
|
||||
( [$(),+] ) => {}; // PASS
|
||||
|
||||
// `?` cannot have a separator...
|
||||
( $($()* $(),* $(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),* )+ ) => {};
|
||||
//~^ 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 $()+)* ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( $(a $()*)+ ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( $(a $()+)? ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
( $(a $()?)+ ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
}
|
||||
|
||||
|
||||
// --- Original Issue --- //
|
||||
|
||||
macro_rules! make_vec {
|
||||
|
@ -43,11 +65,10 @@ fn main() {
|
|||
let _ = make_vec![a 1, a 2, a 3];
|
||||
}
|
||||
|
||||
|
||||
// --- Minified Issue --- //
|
||||
|
||||
macro_rules! m {
|
||||
( $()* ) => {}
|
||||
( $()* ) => {};
|
||||
//~^ ERROR repetition matches empty token tree
|
||||
}
|
||||
|
||||
|
|
|
@ -1,62 +1,110 @@
|
|||
error: repetition matches empty token tree
|
||||
--> $DIR/issue-5067.rs:4:8
|
||||
--> $DIR/issue-5067.rs:9:8
|
||||
|
|
||||
LL | ( $()* ) => {};
|
||||
| ^^
|
||||
|
||||
error: repetition matches empty token tree
|
||||
--> $DIR/issue-5067.rs:6:8
|
||||
--> $DIR/issue-5067.rs:11:8
|
||||
|
|
||||
LL | ( $()+ ) => {};
|
||||
| ^^
|
||||
|
||||
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 | ( [$()*] ) => {};
|
||||
| ^^
|
||||
|
||||
error: repetition matches empty token tree
|
||||
--> $DIR/issue-5067.rs:14:9
|
||||
--> $DIR/issue-5067.rs:20:9
|
||||
|
|
||||
LL | ( [$()+] ) => {};
|
||||
| ^^
|
||||
|
||||
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),* )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: repetition matches empty token tree
|
||||
--> $DIR/issue-5067.rs:22:8
|
||||
--> $DIR/issue-5067.rs:29:8
|
||||
|
|
||||
LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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 $()+)* ) => {};
|
||||
| ^^
|
||||
|
||||
error: repetition matches empty token tree
|
||||
--> $DIR/issue-5067.rs:30:12
|
||||
--> $DIR/issue-5067.rs:49:12
|
||||
|
|
||||
LL | ( $(a $()*)+ ) => {};
|
||||
| ^^
|
||||
|
||||
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)*)*]);
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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