Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/libsyntax/ext/tt/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,10 +696,17 @@ pub fn parse(
} else {
return Failure(parser.span, token::Eof);
}
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why put this in an else?

Copy link
Contributor Author

@ExpHP ExpHP Jul 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Short answer:

To satisfy dropck. (oops, see next comment)


Long answer:

I primarily saw two options here:

Drop eof_items at the beginning of the one branch that is currently affected by the drop. -- This had the disadvantage that future refactorings could easily introduce similar performance regressions (possibly under different conditions).

Drop eof_items as soon as possible. -- This required splitting the large if {} else if {} else if {} ... into two. I saw this as the lesser of two evils, despite the following disadvantages:

  • eof_items must be awkwardly dropped inside an else, since it was moved in the if branch.
  • It takes a bit of careful reading to realize that the if branch unconditionally diverges, especially now that it has an else branch. For this reason, I added the assertion two lines below.

Copy link
Contributor Author

@ExpHP ExpHP Jul 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Right after posting that I decided to double-check on the playground, and it turns out that move analysis is in fact smart enough that the else is not necessary.

That, and now that I look more closely, the if branch here doesn't actually even move eof_items.

// Performance hack: eof_items may share matchers via Rc with other things that we want
// to modify. Dropping eof_items now may drop these refcounts to 1, preventing an
// unnecessary implicit clone later in Rc::make_mut.
drop(eof_items);
}

// Another possibility is that we need to call out to parse some rust nonterminal
// (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
assert!(!token_name_eq(&parser.token, &token::Eof));
if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
let nts = bb_items
.iter()
.map(|item| match item.top_elts.get_tt(item.idx) {
Expand Down