@@ -155,11 +155,11 @@ struct MatcherPos<'tt> {
155155rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 104 ) ;
156156
157157impl < ' tt > MatcherPos < ' tt > {
158- fn top_level ( matcher : & ' tt [ TokenTree ] ) -> Self {
158+ fn top_level ( matcher : & ' tt [ TokenTree ] , empty_matches : Lrc < NamedMatchVec > ) -> Self {
159159 MatcherPos {
160160 tts : matcher,
161161 idx : 0 ,
162- matches : Lrc :: new ( smallvec ! [ ] ) ,
162+ matches : empty_matches ,
163163 seq_depth : 0 ,
164164 match_lo : 0 ,
165165 match_cur : 0 ,
@@ -168,7 +168,11 @@ impl<'tt> MatcherPos<'tt> {
168168 }
169169 }
170170
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 {
172176 let mut mp = MatcherPos {
173177 tts : & seq. tts ,
174178 idx : 0 ,
@@ -182,7 +186,7 @@ impl<'tt> MatcherPos<'tt> {
182186 // Start with an empty vec for each metavar within the sequence. Note that `mp.seq_depth`
183187 // must have the parent's depth at this point for these `push_match` calls to work.
184188 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 ( ) ) ) ;
186190 }
187191 mp. seq_depth += 1 ;
188192 mp
@@ -415,11 +419,21 @@ pub struct TtParser<'tt> {
415419
416420 /// The set of mps that are waiting for the black-box parser.
417421 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 > ,
418426}
419427
420428impl < ' tt > TtParser < ' tt > {
421429 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+ }
423437 }
424438
425439 /// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
@@ -469,13 +483,17 @@ impl<'tt> TtParser<'tt> {
469483 new_mp. match_cur += seq. num_captures ;
470484 new_mp. idx += 1 ;
471485 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 ( ) ) ) ;
473487 }
474488 self . cur_mps . push ( new_mp) ;
475489 }
476490
477491 // 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+ ) ) ;
479497 }
480498
481499 & TokenTree :: MetaVarDecl ( span, _, None ) => {
@@ -621,7 +639,7 @@ impl<'tt> TtParser<'tt> {
621639 // possible next positions into `next_mps`. After some post-processing, the contents of
622640 // `next_mps` replenish `cur_mps` and we start over again.
623641 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 ( ) ) ) ;
625643
626644 loop {
627645 self . next_mps . clear ( ) ;
0 commit comments