Skip to content

Commit

Permalink
Rollup merge of rust-lang#57610 - mark-i-m:nested-matchers, r=petroch…
Browse files Browse the repository at this point in the history
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
  • Loading branch information
Centril authored Jan 17, 2019
2 parents a8c4276 + aa1ce32 commit 4ea266b
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 24 deletions.
14 changes: 10 additions & 4 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}) {
Expand Down Expand Up @@ -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 });
Expand Down Expand Up @@ -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
Expand Down
37 changes: 29 additions & 8 deletions src/test/ui/issues/issue-5067.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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
}

Expand Down
72 changes: 60 additions & 12 deletions src/test/ui/issues/issue-5067.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 80 additions & 0 deletions src/test/ui/issues/issue-57597.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 74 additions & 0 deletions src/test/ui/issues/issue-57597.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4ea266b

Please sign in to comment.