Skip to content

Commit 237df57

Browse files
authored
Rollup merge of rust-lang#57610 - mark-i-m:nested-matchers, r=petrochenkov
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):
2 parents 29e6636 + aa1ce32 commit 237df57

File tree

5 files changed

+253
-24
lines changed

5 files changed

+253
-24
lines changed

src/libsyntax/ext/tt/macro_rules.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
435435
match *seq_tt {
436436
TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
437437
TokenTree::Sequence(_, ref sub_seq) =>
438-
sub_seq.op == quoted::KleeneOp::ZeroOrMore,
438+
sub_seq.op == quoted::KleeneOp::ZeroOrMore
439+
|| sub_seq.op == quoted::KleeneOp::ZeroOrOne,
439440
_ => false,
440441
}
441442
}) {
@@ -543,7 +544,10 @@ impl FirstSets {
543544
}
544545

545546
// Reverse scan: Sequence comes before `first`.
546-
if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore {
547+
if subfirst.maybe_empty
548+
|| seq_rep.op == quoted::KleeneOp::ZeroOrMore
549+
|| seq_rep.op == quoted::KleeneOp::ZeroOrOne
550+
{
547551
// If sequence is potentially empty, then
548552
// union them (preserving first emptiness).
549553
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
@@ -591,8 +595,10 @@ impl FirstSets {
591595

592596
assert!(first.maybe_empty);
593597
first.add_all(subfirst);
594-
if subfirst.maybe_empty ||
595-
seq_rep.op == quoted::KleeneOp::ZeroOrMore {
598+
if subfirst.maybe_empty
599+
|| seq_rep.op == quoted::KleeneOp::ZeroOrMore
600+
|| seq_rep.op == quoted::KleeneOp::ZeroOrOne
601+
{
596602
// continue scanning for more first
597603
// tokens, but also make sure we
598604
// restore empty-tracking state

src/test/ui/issues/issue-5067.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,59 @@
11
#![allow(unused_macros)]
22

3+
// Tests that repetition matchers cannot match the empty token tree (since that would be
4+
// ambiguous).
5+
6+
// edition:2018
7+
38
macro_rules! foo {
49
( $()* ) => {};
510
//~^ ERROR repetition matches empty token tree
611
( $()+ ) => {};
712
//~^ ERROR repetition matches empty token tree
8-
13+
( $()? ) => {};
14+
//~^ ERROR repetition matches empty token tree
915
( $(),* ) => {}; // PASS
1016
( $(),+ ) => {}; // PASS
11-
17+
// `?` cannot have a separator...
1218
( [$()*] ) => {};
1319
//~^ ERROR repetition matches empty token tree
1420
( [$()+] ) => {};
1521
//~^ ERROR repetition matches empty token tree
16-
22+
( [$()?] ) => {};
23+
//~^ ERROR repetition matches empty token tree
1724
( [$(),*] ) => {}; // PASS
1825
( [$(),+] ) => {}; // PASS
19-
26+
// `?` cannot have a separator...
2027
( $($()* $(),* $(a)* $(a),* )* ) => {};
2128
//~^ ERROR repetition matches empty token tree
2229
( $($()* $(),* $(a)* $(a),* )+ ) => {};
2330
//~^ ERROR repetition matches empty token tree
24-
31+
( $($()* $(),* $(a)* $(a),* )? ) => {};
32+
//~^ ERROR repetition matches empty token tree
33+
( $($()? $(),* $(a)? $(a),* )* ) => {};
34+
//~^ ERROR repetition matches empty token tree
35+
( $($()? $(),* $(a)? $(a),* )+ ) => {};
36+
//~^ ERROR repetition matches empty token tree
37+
( $($()? $(),* $(a)? $(a),* )? ) => {};
38+
//~^ ERROR repetition matches empty token tree
2539
( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS
2640
( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS
41+
( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS
42+
43+
( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS
44+
( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS
45+
( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS
2746

2847
( $(a $()+)* ) => {};
2948
//~^ ERROR repetition matches empty token tree
3049
( $(a $()*)+ ) => {};
3150
//~^ ERROR repetition matches empty token tree
51+
( $(a $()+)? ) => {};
52+
//~^ ERROR repetition matches empty token tree
53+
( $(a $()?)+ ) => {};
54+
//~^ ERROR repetition matches empty token tree
3255
}
3356

34-
3557
// --- Original Issue --- //
3658

3759
macro_rules! make_vec {
@@ -43,11 +65,10 @@ fn main() {
4365
let _ = make_vec![a 1, a 2, a 3];
4466
}
4567

46-
4768
// --- Minified Issue --- //
4869

4970
macro_rules! m {
50-
( $()* ) => {}
71+
( $()* ) => {};
5172
//~^ ERROR repetition matches empty token tree
5273
}
5374

src/test/ui/issues/issue-5067.stderr

+60-12
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,110 @@
11
error: repetition matches empty token tree
2-
--> $DIR/issue-5067.rs:4:8
2+
--> $DIR/issue-5067.rs:9:8
33
|
44
LL | ( $()* ) => {};
55
| ^^
66

77
error: repetition matches empty token tree
8-
--> $DIR/issue-5067.rs:6:8
8+
--> $DIR/issue-5067.rs:11:8
99
|
1010
LL | ( $()+ ) => {};
1111
| ^^
1212

1313
error: repetition matches empty token tree
14-
--> $DIR/issue-5067.rs:12:9
14+
--> $DIR/issue-5067.rs:13:8
15+
|
16+
LL | ( $()? ) => {};
17+
| ^^
18+
19+
error: repetition matches empty token tree
20+
--> $DIR/issue-5067.rs:18:9
1521
|
1622
LL | ( [$()*] ) => {};
1723
| ^^
1824

1925
error: repetition matches empty token tree
20-
--> $DIR/issue-5067.rs:14:9
26+
--> $DIR/issue-5067.rs:20:9
2127
|
2228
LL | ( [$()+] ) => {};
2329
| ^^
2430

2531
error: repetition matches empty token tree
26-
--> $DIR/issue-5067.rs:20:8
32+
--> $DIR/issue-5067.rs:22:9
33+
|
34+
LL | ( [$()?] ) => {};
35+
| ^^
36+
37+
error: repetition matches empty token tree
38+
--> $DIR/issue-5067.rs:27:8
2739
|
2840
LL | ( $($()* $(),* $(a)* $(a),* )* ) => {};
2941
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3042

3143
error: repetition matches empty token tree
32-
--> $DIR/issue-5067.rs:22:8
44+
--> $DIR/issue-5067.rs:29:8
3345
|
3446
LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {};
3547
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3648

3749
error: repetition matches empty token tree
38-
--> $DIR/issue-5067.rs:28:12
50+
--> $DIR/issue-5067.rs:31:8
51+
|
52+
LL | ( $($()* $(),* $(a)* $(a),* )? ) => {};
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
55+
error: repetition matches empty token tree
56+
--> $DIR/issue-5067.rs:33:8
57+
|
58+
LL | ( $($()? $(),* $(a)? $(a),* )* ) => {};
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
60+
61+
error: repetition matches empty token tree
62+
--> $DIR/issue-5067.rs:35:8
63+
|
64+
LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {};
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
66+
67+
error: repetition matches empty token tree
68+
--> $DIR/issue-5067.rs:37:8
69+
|
70+
LL | ( $($()? $(),* $(a)? $(a),* )? ) => {};
71+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
72+
73+
error: repetition matches empty token tree
74+
--> $DIR/issue-5067.rs:47:12
3975
|
4076
LL | ( $(a $()+)* ) => {};
4177
| ^^
4278

4379
error: repetition matches empty token tree
44-
--> $DIR/issue-5067.rs:30:12
80+
--> $DIR/issue-5067.rs:49:12
4581
|
4682
LL | ( $(a $()*)+ ) => {};
4783
| ^^
4884

4985
error: repetition matches empty token tree
50-
--> $DIR/issue-5067.rs:38:18
86+
--> $DIR/issue-5067.rs:51:12
87+
|
88+
LL | ( $(a $()+)? ) => {};
89+
| ^^
90+
91+
error: repetition matches empty token tree
92+
--> $DIR/issue-5067.rs:53:12
93+
|
94+
LL | ( $(a $()?)+ ) => {};
95+
| ^^
96+
97+
error: repetition matches empty token tree
98+
--> $DIR/issue-5067.rs:60:18
5199
|
52100
LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
53101
| ^^^^^^^^^^^^^^^^^^
54102

55103
error: repetition matches empty token tree
56-
--> $DIR/issue-5067.rs:50:8
104+
--> $DIR/issue-5067.rs:71:8
57105
|
58-
LL | ( $()* ) => {}
106+
LL | ( $()* ) => {};
59107
| ^^
60108

61-
error: aborting due to 10 previous errors
109+
error: aborting due to 18 previous errors
62110

src/test/ui/issues/issue-57597.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Regression test for #57597.
2+
//
3+
// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
4+
5+
// edition:2018
6+
7+
macro_rules! foo1 {
8+
($($($i:ident)?)+) => {};
9+
//~^ ERROR repetition matches empty token tree
10+
}
11+
12+
macro_rules! foo2 {
13+
($($($i:ident)?)*) => {};
14+
//~^ ERROR repetition matches empty token tree
15+
}
16+
17+
macro_rules! foo3 {
18+
($($($i:ident)?)?) => {};
19+
//~^ ERROR repetition matches empty token tree
20+
}
21+
22+
macro_rules! foo4 {
23+
($($($($i:ident)?)?)?) => {};
24+
//~^ ERROR repetition matches empty token tree
25+
}
26+
27+
macro_rules! foo5 {
28+
($($($($i:ident)*)?)?) => {};
29+
//~^ ERROR repetition matches empty token tree
30+
}
31+
32+
macro_rules! foo6 {
33+
($($($($i:ident)?)*)?) => {};
34+
//~^ ERROR repetition matches empty token tree
35+
}
36+
37+
macro_rules! foo7 {
38+
($($($($i:ident)?)?)*) => {};
39+
//~^ ERROR repetition matches empty token tree
40+
}
41+
42+
macro_rules! foo8 {
43+
($($($($i:ident)*)*)?) => {};
44+
//~^ ERROR repetition matches empty token tree
45+
}
46+
47+
macro_rules! foo9 {
48+
($($($($i:ident)?)*)*) => {};
49+
//~^ ERROR repetition matches empty token tree
50+
}
51+
52+
macro_rules! foo10 {
53+
($($($($i:ident)?)*)+) => {};
54+
//~^ ERROR repetition matches empty token tree
55+
}
56+
57+
macro_rules! foo11 {
58+
($($($($i:ident)+)?)*) => {};
59+
//~^ ERROR repetition matches empty token tree
60+
}
61+
62+
macro_rules! foo12 {
63+
($($($($i:ident)+)*)?) => {};
64+
//~^ ERROR repetition matches empty token tree
65+
}
66+
67+
fn main() {
68+
foo1!();
69+
foo2!();
70+
foo3!();
71+
foo4!();
72+
foo5!();
73+
foo6!();
74+
foo7!();
75+
foo8!();
76+
foo9!();
77+
foo10!();
78+
foo11!();
79+
foo12!();
80+
}

src/test/ui/issues/issue-57597.stderr

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
error: repetition matches empty token tree
2+
--> $DIR/issue-57597.rs:8:7
3+
|
4+
LL | ($($($i:ident)?)+) => {};
5+
| ^^^^^^^^^^^^^^
6+
7+
error: repetition matches empty token tree
8+
--> $DIR/issue-57597.rs:13:7
9+
|
10+
LL | ($($($i:ident)?)*) => {};
11+
| ^^^^^^^^^^^^^^
12+
13+
error: repetition matches empty token tree
14+
--> $DIR/issue-57597.rs:18:7
15+
|
16+
LL | ($($($i:ident)?)?) => {};
17+
| ^^^^^^^^^^^^^^
18+
19+
error: repetition matches empty token tree
20+
--> $DIR/issue-57597.rs:23:7
21+
|
22+
LL | ($($($($i:ident)?)?)?) => {};
23+
| ^^^^^^^^^^^^^^^^^^
24+
25+
error: repetition matches empty token tree
26+
--> $DIR/issue-57597.rs:28:7
27+
|
28+
LL | ($($($($i:ident)*)?)?) => {};
29+
| ^^^^^^^^^^^^^^^^^^
30+
31+
error: repetition matches empty token tree
32+
--> $DIR/issue-57597.rs:33:7
33+
|
34+
LL | ($($($($i:ident)?)*)?) => {};
35+
| ^^^^^^^^^^^^^^^^^^
36+
37+
error: repetition matches empty token tree
38+
--> $DIR/issue-57597.rs:38:7
39+
|
40+
LL | ($($($($i:ident)?)?)*) => {};
41+
| ^^^^^^^^^^^^^^^^^^
42+
43+
error: repetition matches empty token tree
44+
--> $DIR/issue-57597.rs:43:7
45+
|
46+
LL | ($($($($i:ident)*)*)?) => {};
47+
| ^^^^^^^^^^^^^^^^^^
48+
49+
error: repetition matches empty token tree
50+
--> $DIR/issue-57597.rs:48:7
51+
|
52+
LL | ($($($($i:ident)?)*)*) => {};
53+
| ^^^^^^^^^^^^^^^^^^
54+
55+
error: repetition matches empty token tree
56+
--> $DIR/issue-57597.rs:53:7
57+
|
58+
LL | ($($($($i:ident)?)*)+) => {};
59+
| ^^^^^^^^^^^^^^^^^^
60+
61+
error: repetition matches empty token tree
62+
--> $DIR/issue-57597.rs:58:7
63+
|
64+
LL | ($($($($i:ident)+)?)*) => {};
65+
| ^^^^^^^^^^^^^^^^^^
66+
67+
error: repetition matches empty token tree
68+
--> $DIR/issue-57597.rs:63:7
69+
|
70+
LL | ($($($($i:ident)+)*)?) => {};
71+
| ^^^^^^^^^^^^^^^^^^
72+
73+
error: aborting due to 12 previous errors
74+

0 commit comments

Comments
 (0)