Skip to content

Commit 048bd67

Browse files
committed
Clarify idx handling in sequences.
By adding comments, and improving an assertion. I finally fully understand this part!
1 parent 2e423c7 commit 048bd67

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

compiler/rustc_expand/src/mbe/macro_parser.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ struct MatcherPos<'tt> {
122122
/// submatcher, this is just the contents of that submatcher.
123123
tts: &'tt [TokenTree],
124124

125-
/// The "dot" position within the current submatcher, i.e. the index into `tts`.
125+
/// The "dot" position within the current submatcher, i.e. the index into `tts`. Can go one or
126+
/// two positions past the final elements in `tts` when dealing with sequences, see
127+
/// `parse_tt_inner` for details.
126128
idx: usize,
127129

128130
/// This vector ends up with one element per metavar in the *top-level* matcher, even when this
@@ -540,20 +542,26 @@ impl<'tt> TtParser<'tt> {
540542
}
541543
} else if let Some(sequence) = &mp.sequence {
542544
// We are past the end of a sequence.
543-
debug_assert!(idx <= len + 1);
545+
// - If it has no separator, we must be only one past the end.
546+
// - If it has a separator, we may be one past the end, in which case we must
547+
// look for a separator. Or we may be two past the end, in which case we have
548+
// already dealt with the separator.
549+
debug_assert!(idx == len || idx == len + 1 && sequence.seq.separator.is_some());
544550

545551
if idx == len {
546-
// Add all matches from the sequence to `parent`, and move the "dot" past the
547-
// sequence in `parent`. This allows for the case where the sequence matching
548-
// is finished.
552+
// Sequence matching may have finished: move the "dot" past the sequence in
553+
// `parent`. This applies whether a separator is used or not. If sequence
554+
// matching hasn't finished, this `new_mp` will fail quietly when it is
555+
// processed next time around the loop.
549556
let mut new_mp = sequence.parent.clone();
550557
new_mp.matches = mp.matches.clone();
551558
new_mp.match_cur = mp.match_cur;
552559
new_mp.idx += 1;
553560
self.cur_mps.push(new_mp);
554561
}
555562

556-
if idx == len && sequence.seq.separator.is_some() {
563+
if sequence.seq.separator.is_some() && idx == len {
564+
// Look for the separator.
557565
if sequence
558566
.seq
559567
.separator
@@ -566,9 +574,10 @@ impl<'tt> TtParser<'tt> {
566574
self.next_mps.push(mp);
567575
}
568576
} else if sequence.seq.kleene.op != mbe::KleeneOp::ZeroOrOne {
569-
// We don't need a separator. Move the "dot" back to the beginning of the
570-
// matcher and try to match again UNLESS we are only allowed to have _one_
571-
// repetition.
577+
// We don't need to look for a separator: either this sequence doesn't have
578+
// one, or it does and we've already handled it. Also, we are allowed to have
579+
// more than one repetition. Move the "dot" back to the beginning of the
580+
// matcher and try to match again.
572581
mp.match_cur -= sequence.seq.num_captures;
573582
mp.idx = 0;
574583
self.cur_mps.push(mp);

0 commit comments

Comments
 (0)