Skip to content

Commit e5f3fd6

Browse files
committed
Use a better return type for inner_parse_loop.
Because `inner_parse_loop` has only one way to not succeed, not three.
1 parent 643ba50 commit e5f3fd6

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

compiler/rustc_expand/src/mbe/macro_parser.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,12 @@ impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> {
266266
}
267267
}
268268

269+
enum EofItems<'root, 'tt> {
270+
None,
271+
One(MatcherPosHandle<'root, 'tt>),
272+
Multiple,
273+
}
274+
269275
/// Represents the possible results of an attempted parse.
270276
crate enum ParseResult<T> {
271277
/// Parsed successfully.
@@ -449,10 +455,10 @@ fn inner_parse_loop<'root, 'tt>(
449455
sess: &ParseSess,
450456
cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
451457
next_items: &mut Vec<MatcherPosHandle<'root, 'tt>>,
452-
eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
453458
bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
459+
eof_items: &mut EofItems<'root, 'tt>,
454460
token: &Token,
455-
) -> ParseResult<()> {
461+
) -> Result<(), (rustc_span::Span, String)> {
456462
// Pop items from `cur_items` until it is empty.
457463
while let Some(mut item) = cur_items.pop() {
458464
// When unzipped trees end, remove them. This corresponds to backtracking out of a
@@ -522,7 +528,10 @@ fn inner_parse_loop<'root, 'tt>(
522528
} else {
523529
// If we are not in a repetition, then being at the end of a matcher means that we
524530
// have reached the potential end of the input.
525-
eof_items.push(item);
531+
*eof_items = match eof_items {
532+
EofItems::None => EofItems::One(item),
533+
EofItems::One(_) | EofItems::Multiple => EofItems::Multiple,
534+
}
526535
}
527536
} else {
528537
// We are in the middle of a matcher. Look at what token in the matcher we are trying
@@ -567,7 +576,7 @@ fn inner_parse_loop<'root, 'tt>(
567576
// We need to match a metavar (but the identifier is invalid)... this is an error
568577
TokenTree::MetaVarDecl(span, _, None) => {
569578
if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
570-
return Error(span, "missing fragment specifier".to_string());
579+
return Err((span, "missing fragment specifier".to_string()));
571580
}
572581
}
573582

@@ -615,7 +624,7 @@ fn inner_parse_loop<'root, 'tt>(
615624
}
616625

617626
// Yay a successful parse (so far)!
618-
Success(())
627+
Ok(())
619628
}
620629

621630
/// Use the given sequence of token trees (`ms`) as a matcher. Match the token
@@ -638,12 +647,13 @@ pub(super) fn parse_tt(
638647
let mut next_items = Vec::new();
639648

640649
loop {
650+
assert!(next_items.is_empty());
651+
641652
// Matcher positions black-box parsed by parser.rs (`parser`)
642653
let mut bb_items = SmallVec::new();
643654

644655
// Matcher positions that would be valid if the macro invocation was over now
645-
let mut eof_items = SmallVec::new();
646-
assert!(next_items.is_empty());
656+
let mut eof_items = EofItems::None;
647657

648658
// Process `cur_items` until either we have finished the input or we need to get some
649659
// parsing from the black-box parser done. The result is that `next_items` will contain a
@@ -652,34 +662,34 @@ pub(super) fn parse_tt(
652662
parser.sess,
653663
&mut cur_items,
654664
&mut next_items,
655-
&mut eof_items,
656665
&mut bb_items,
666+
&mut eof_items,
657667
&parser.token,
658668
) {
659-
Success(_) => {}
660-
Failure(token, msg) => return Failure(token, msg),
661-
Error(sp, msg) => return Error(sp, msg),
662-
ErrorReported => return ErrorReported,
669+
Ok(()) => {}
670+
Err((sp, msg)) => return Error(sp, msg),
663671
}
664672

665673
// inner parse loop handled all cur_items, so it's empty
666674
assert!(cur_items.is_empty());
667675

668-
// We need to do some post processing after the `inner_parser_loop`.
676+
// We need to do some post processing after the `inner_parse_loop`.
669677
//
670678
// Error messages here could be improved with links to original rules.
671679

672680
// If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
673681
// either the parse is ambiguous (which should never happen) or there is a syntax error.
674682
if parser.token == token::Eof {
675-
return if eof_items.len() == 1 {
676-
let matches =
677-
eof_items[0].matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
678-
nameize(parser.sess, ms, matches)
679-
} else if eof_items.len() > 1 {
680-
Error(parser.token.span, "ambiguity: multiple successful parses".to_string())
681-
} else {
682-
Failure(
683+
return match eof_items {
684+
EofItems::One(mut eof_item) => {
685+
let matches =
686+
eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
687+
nameize(parser.sess, ms, matches)
688+
}
689+
EofItems::Multiple => {
690+
Error(parser.token.span, "ambiguity: multiple successful parses".to_string())
691+
}
692+
EofItems::None => Failure(
683693
Token::new(
684694
token::Eof,
685695
if parser.token.span.is_dummy() {
@@ -689,12 +699,12 @@ pub(super) fn parse_tt(
689699
},
690700
),
691701
"missing tokens in macro arguments",
692-
)
702+
),
693703
};
694704
}
695-
// Performance hack: eof_items may share matchers via Rc with other things that we want
696-
// to modify. Dropping eof_items now may drop these refcounts to 1, preventing an
697-
// unnecessary implicit clone later in Rc::make_mut.
705+
// Performance hack: `eof_items` may share matchers via `Rc` with other things that we want
706+
// to modify. Dropping `eof_items` now may drop these refcounts to 1, preventing an
707+
// unnecessary implicit clone later in `Rc::make_mut`.
698708
drop(eof_items);
699709

700710
// If there are no possible next positions AND we aren't waiting for the black-box parser,

0 commit comments

Comments
 (0)