@@ -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