Skip to content

Commit 257d854

Browse files
committed
Auto merge of #52145 - ExpHP:drop-it-like-its-eof, r=<try>
Fix macro parser quadratic complexity in small repeating groups Observed in #51754, and more easily demonstrated with the following: ```rust macro_rules! stress { ($($t:tt)+) => { }; } fn main() { stress!{ a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a // ... 65536 copies of "a" total ... a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a } } ``` which takes 50 seconds to compile prior to the fix and <1s after. I hope this has a visible impact on the compile times for real code. (I think it is most likely to affect incremental TT munchers that deal with large inputs, though it depends on how they are written) For a fuller description of the performance issue: #51754 (comment) --- There is no test (yet) because I'm not sure how easily to measure this for regressions.
2 parents 0e6b713 + 191e76c commit 257d854

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

Diff for: src/libsyntax/ext/tt/macro_parser.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -696,10 +696,17 @@ pub fn parse(
696696
} else {
697697
return Failure(parser.span, token::Eof);
698698
}
699+
} else {
700+
// Performance hack: eof_items may share matchers via Rc with other things that we want
701+
// to modify. Dropping eof_items now may drop these refcounts to 1, preventing an
702+
// unnecessary implicit clone later in Rc::make_mut.
703+
drop(eof_items);
699704
}
705+
700706
// Another possibility is that we need to call out to parse some rust nonterminal
701707
// (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
702-
else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
708+
assert!(!token_name_eq(&parser.token, &token::Eof));
709+
if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
703710
let nts = bb_items
704711
.iter()
705712
.map(|item| match item.top_elts.get_tt(item.idx) {

0 commit comments

Comments
 (0)