@@ -101,7 +101,14 @@ struct MatcherTtFrame<'tt> {
101101 idx : usize ,
102102}
103103
104- type NamedMatchVec = SmallVec < [ NamedMatch ; 4 ] > ;
104+ // One element is enough to cover 95-99% of vectors for most benchmarks. Also,
105+ // vectors longer than one frequently have many elements, not just two or
106+ // three.
107+ type NamedMatchVec = SmallVec < [ NamedMatch ; 1 ] > ;
108+
109+ // This type is used a lot. Make sure it doesn't unintentionally get bigger.
110+ #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
111+ rustc_data_structures:: static_assert_size!( NamedMatchVec , 48 ) ;
105112
106113/// Represents a single "position" (aka "matcher position", aka "item"), as
107114/// described in the module documentation.
@@ -153,7 +160,7 @@ struct MatcherPos<'tt> {
153160
154161// This type is used a lot. Make sure it doesn't unintentionally get bigger.
155162#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
156- rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 136 ) ;
163+ rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 112 ) ;
157164
158165impl < ' tt > MatcherPos < ' tt > {
159166 /// `len` `Vec`s (initially shared and empty) that will store matches of metavars.
@@ -202,11 +209,7 @@ impl<'tt> MatcherPos<'tt> {
202209 match_lo : up. match_cur ,
203210 match_cur : up. match_cur ,
204211 match_hi : up. match_cur + seq. num_captures ,
205- repetition : Some ( MatcherPosRepetition {
206- up,
207- sep : seq. separator . clone ( ) ,
208- seq_op : seq. kleene . op ,
209- } ) ,
212+ repetition : Some ( MatcherPosRepetition { up, seq } ) ,
210213 stack : smallvec ! [ ] ,
211214 }
212215 }
@@ -220,15 +223,12 @@ impl<'tt> MatcherPos<'tt> {
220223
221224#[ derive( Clone ) ]
222225struct MatcherPosRepetition < ' tt > {
223- /// The KleeneOp of this sequence.
224- seq_op : mbe:: KleeneOp ,
225-
226- /// The separator.
227- sep : Option < Token > ,
228-
229226 /// The "parent" matcher position. That is, the matcher position just before we enter the
230227 /// sequence.
231228 up : Box < MatcherPos < ' tt > > ,
229+
230+ /// The sequence itself.
231+ seq : & ' tt SequenceRepetition ,
232232}
233233
234234enum EofItems < ' tt > {
@@ -274,22 +274,20 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
274274 } )
275275}
276276
277- /// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`:
278- /// so it is associated with a single ident in a parse, and all
279- /// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
280- /// (expr, item, etc). Each leaf in a single `NamedMatch` corresponds to a
281- /// single `token::MATCH_NONTERMINAL` in the `TokenTree` that produced it.
277+ /// `NamedMatch` is a pattern-match result for a single metavar. All
278+ /// `MatchedNtNonTt`s in the `NamedMatch` have the same non-terminal type
279+ /// (expr, item, etc).
282280///
283281/// The in-memory structure of a particular `NamedMatch` represents the match
284282/// that occurred when a particular subset of a matcher was applied to a
285283/// particular token tree.
286284///
287285/// The width of each `MatchedSeq` in the `NamedMatch`, and the identity of
288- /// the `MatchedNonterminal `s, will depend on the token tree it was applied
289- /// to: each `MatchedSeq` corresponds to a single `TTSeq` in the originating
286+ /// the `MatchedNtNonTts `s, will depend on the token tree it was applied
287+ /// to: each `MatchedSeq` corresponds to a single repetition in the originating
290288/// token tree. The depth of the `NamedMatch` structure will therefore depend
291- /// only on the nesting depth of `ast::TTSeq`s in the originating
292- /// token tree it was derived from.
289+ /// only on the nesting depth of repetitions in the originating token tree it
290+ /// was derived from.
293291///
294292/// In layman's terms: `NamedMatch` will form a tree representing nested matches of a particular
295293/// meta variable. For example, if we are matching the following macro against the following
@@ -308,24 +306,32 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
308306/// ```rust
309307/// MatchedSeq([
310308/// MatchedSeq([
311- /// MatchedNonterminal (a),
312- /// MatchedNonterminal (b),
313- /// MatchedNonterminal (c),
314- /// MatchedNonterminal (d),
309+ /// MatchedNtNonTt (a),
310+ /// MatchedNtNonTt (b),
311+ /// MatchedNtNonTt (c),
312+ /// MatchedNtNonTt (d),
315313/// ]),
316314/// MatchedSeq([
317- /// MatchedNonterminal (a),
318- /// MatchedNonterminal (b),
319- /// MatchedNonterminal (c),
320- /// MatchedNonterminal (d),
321- /// MatchedNonterminal (e),
315+ /// MatchedNtNonTt (a),
316+ /// MatchedNtNonTt (b),
317+ /// MatchedNtNonTt (c),
318+ /// MatchedNtNonTt (d),
319+ /// MatchedNtNonTt (e),
322320/// ])
323321/// ])
324322/// ```
325323#[ derive( Debug , Clone ) ]
326324crate enum NamedMatch {
327325 MatchedSeq ( Lrc < NamedMatchVec > ) ,
328- MatchedNonterminal ( Lrc < Nonterminal > ) ,
326+
327+ // This variant should never hold an `NtTT`. `MatchedNtTt` should be used
328+ // for that case.
329+ MatchedNtNonTt ( Lrc < Nonterminal > ) ,
330+
331+ // `NtTT` is handled without any cloning when transcribing, unlike other
332+ // nonterminals. Therefore, an `Lrc` isn't helpful and causes unnecessary
333+ // allocations. Hence this separate variant.
334+ MatchedNtTt ( rustc_ast:: tokenstream:: TokenTree ) ,
329335}
330336
331337/// Takes a slice of token trees `ms` representing a matcher which successfully matched input
@@ -546,14 +552,19 @@ impl<'tt> TtParser<'tt> {
546552 self . cur_items . push ( new_pos) ;
547553 }
548554
549- if idx == len && repetition. sep . is_some ( ) {
550- if repetition. sep . as_ref ( ) . map_or ( false , |sep| token_name_eq ( token, sep) ) {
555+ if idx == len && repetition. seq . separator . is_some ( ) {
556+ if repetition
557+ . seq
558+ . separator
559+ . as_ref ( )
560+ . map_or ( false , |sep| token_name_eq ( token, sep) )
561+ {
551562 // The matcher has a separator, and it matches the current token. We can
552563 // advance past the separator token.
553564 item. idx += 1 ;
554565 self . next_items . push ( item) ;
555566 }
556- } else if repetition. seq_op != mbe:: KleeneOp :: ZeroOrOne {
567+ } else if repetition. seq . kleene . op != mbe:: KleeneOp :: ZeroOrOne {
557568 // We don't need a separator. Move the "dot" back to the beginning of the
558569 // matcher and try to match again UNLESS we are only allowed to have _one_
559570 // repetition.
@@ -665,7 +676,11 @@ impl<'tt> TtParser<'tt> {
665676 }
666677 Ok ( nt) => nt,
667678 } ;
668- item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
679+ let m = match nt {
680+ Nonterminal :: NtTT ( tt) => MatchedNtTt ( tt) ,
681+ _ => MatchedNtNonTt ( Lrc :: new ( nt) ) ,
682+ } ;
683+ item. push_match ( match_cur, m) ;
669684 item. idx += 1 ;
670685 item. match_cur += 1 ;
671686 } else {
0 commit comments