@@ -155,11 +155,11 @@ struct MatcherPos<'tt> {
155
155
rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 104 ) ;
156
156
157
157
impl < ' tt > MatcherPos < ' tt > {
158
- fn top_level ( matcher : & ' tt [ TokenTree ] ) -> Self {
158
+ fn top_level ( matcher : & ' tt [ TokenTree ] , empty_matches : Lrc < NamedMatchVec > ) -> Self {
159
159
MatcherPos {
160
160
tts : matcher,
161
161
idx : 0 ,
162
- matches : Lrc :: new ( smallvec ! [ ] ) ,
162
+ matches : empty_matches ,
163
163
seq_depth : 0 ,
164
164
match_lo : 0 ,
165
165
match_cur : 0 ,
@@ -168,7 +168,11 @@ impl<'tt> MatcherPos<'tt> {
168
168
}
169
169
}
170
170
171
- fn sequence ( parent : Box < MatcherPos < ' tt > > , seq : & ' tt SequenceRepetition ) -> Self {
171
+ fn sequence (
172
+ parent : Box < MatcherPos < ' tt > > ,
173
+ seq : & ' tt SequenceRepetition ,
174
+ empty_matches : Lrc < NamedMatchVec > ,
175
+ ) -> Self {
172
176
let mut mp = MatcherPos {
173
177
tts : & seq. tts ,
174
178
idx : 0 ,
@@ -182,7 +186,7 @@ impl<'tt> MatcherPos<'tt> {
182
186
// Start with an empty vec for each metavar within the sequence. Note that `mp.seq_depth`
183
187
// must have the parent's depth at this point for these `push_match` calls to work.
184
188
for idx in mp. match_lo ..mp. match_lo + seq. num_captures {
185
- mp. push_match ( idx, MatchedSeq ( Lrc :: new ( smallvec ! [ ] ) ) ) ;
189
+ mp. push_match ( idx, MatchedSeq ( empty_matches . clone ( ) ) ) ;
186
190
}
187
191
mp. seq_depth += 1 ;
188
192
mp
@@ -415,11 +419,21 @@ pub struct TtParser<'tt> {
415
419
416
420
/// The set of mps that are waiting for the black-box parser.
417
421
bb_mps : Vec < Box < MatcherPos < ' tt > > > ,
422
+
423
+ /// Pre-allocate an empty match array, so it can be cloned cheaply for macros with many rules
424
+ /// that have no metavars.
425
+ empty_matches : Lrc < NamedMatchVec > ,
418
426
}
419
427
420
428
impl < ' tt > TtParser < ' tt > {
421
429
pub ( super ) fn new ( macro_name : Ident ) -> TtParser < ' tt > {
422
- TtParser { macro_name, cur_mps : vec ! [ ] , next_mps : vec ! [ ] , bb_mps : vec ! [ ] }
430
+ TtParser {
431
+ macro_name,
432
+ cur_mps : vec ! [ ] ,
433
+ next_mps : vec ! [ ] ,
434
+ bb_mps : vec ! [ ] ,
435
+ empty_matches : Lrc :: new ( smallvec ! [ ] ) ,
436
+ }
423
437
}
424
438
425
439
/// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
@@ -469,13 +483,17 @@ impl<'tt> TtParser<'tt> {
469
483
new_mp. match_cur += seq. num_captures ;
470
484
new_mp. idx += 1 ;
471
485
for idx in mp. match_cur ..mp. match_cur + seq. num_captures {
472
- new_mp. push_match ( idx, MatchedSeq ( Lrc :: new ( smallvec ! [ ] ) ) ) ;
486
+ new_mp. push_match ( idx, MatchedSeq ( self . empty_matches . clone ( ) ) ) ;
473
487
}
474
488
self . cur_mps . push ( new_mp) ;
475
489
}
476
490
477
491
// Allow for the possibility of one or more matches of this sequence.
478
- self . cur_mps . push ( box MatcherPos :: sequence ( mp, & seq) ) ;
492
+ self . cur_mps . push ( box MatcherPos :: sequence (
493
+ mp,
494
+ & seq,
495
+ self . empty_matches . clone ( ) ,
496
+ ) ) ;
479
497
}
480
498
481
499
& TokenTree :: MetaVarDecl ( span, _, None ) => {
@@ -621,7 +639,7 @@ impl<'tt> TtParser<'tt> {
621
639
// possible next positions into `next_mps`. After some post-processing, the contents of
622
640
// `next_mps` replenish `cur_mps` and we start over again.
623
641
self . cur_mps . clear ( ) ;
624
- self . cur_mps . push ( box MatcherPos :: top_level ( matcher) ) ;
642
+ self . cur_mps . push ( box MatcherPos :: top_level ( matcher, self . empty_matches . clone ( ) ) ) ;
625
643
626
644
loop {
627
645
self . next_mps . clear ( ) ;
0 commit comments