Skip to content

Commit 2a5487a

Browse files
committed
Merge TokenStreamBuilder::push into TokenStreamBuilder::build.
Both functions do some modifying of streams using `make_mut`: - `push` sometimes glues the first token of the next stream to the last token of the first stream. - `build` appends tokens to the first stream. By doing all of this in the one place, things are simpler. The first stream can be modified in both ways (if necessary) in the one place, and any next stream with the first token removed doesn't need to be stored.
1 parent f6b5788 commit 2a5487a

File tree

1 file changed

+32
-53
lines changed

1 file changed

+32
-53
lines changed

compiler/rustc_ast/src/tokenstream.rs

+32-53
Original file line numberDiff line numberDiff line change
@@ -523,46 +523,7 @@ impl TokenStreamBuilder {
523523
}
524524

525525
pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
526-
let mut stream = stream.into();
527-
528-
// If `self` is not empty and the last tree within the last stream is a
529-
// token tree marked with `Joint`...
530-
if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut()
531-
&& let Some((TokenTree::Token(last_token), Spacing::Joint)) = last_stream_lrc.last()
532-
// ...and `stream` is not empty and the first tree within it is
533-
// a token tree...
534-
&& let TokenStream(ref mut stream_lrc) = stream
535-
&& let Some((TokenTree::Token(token), spacing)) = stream_lrc.first()
536-
// ...and the two tokens can be glued together...
537-
&& let Some(glued_tok) = last_token.glue(&token)
538-
{
539-
// ...then do so, by overwriting the last token
540-
// tree in `self` and removing the first token tree
541-
// from `stream`. This requires using `make_mut()`
542-
// on the last stream in `self` and on `stream`,
543-
// and in practice this doesn't cause cloning 99.9%
544-
// of the time.
545-
546-
// Overwrite the last token tree with the merged
547-
// token.
548-
let last_vec_mut = Lrc::make_mut(last_stream_lrc);
549-
*last_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
550-
551-
// Remove the first token tree from `stream`. (This
552-
// is almost always the only tree in `stream`.)
553-
let stream_vec_mut = Lrc::make_mut(stream_lrc);
554-
stream_vec_mut.remove(0);
555-
556-
// Don't push `stream` if it's empty -- that could
557-
// block subsequent token gluing, by getting
558-
// between two token trees that should be glued
559-
// together.
560-
if !stream.is_empty() {
561-
self.0.push(stream);
562-
}
563-
return;
564-
}
565-
self.0.push(stream);
526+
self.0.push(stream.into());
566527
}
567528

568529
pub fn build(self) -> TokenStream {
@@ -571,9 +532,9 @@ impl TokenStreamBuilder {
571532
0 => TokenStream::default(),
572533
1 => streams.pop().unwrap(),
573534
_ => {
574-
// We are going to extend the first stream in `streams` with
575-
// the elements from the subsequent streams. This requires
576-
// using `make_mut()` on the first stream, and in practice this
535+
// We will extend the first stream in `streams` with the
536+
// elements from the subsequent streams. This requires using
537+
// `make_mut()` on the first stream, and in practice this
577538
// doesn't cause cloning 99.9% of the time.
578539
//
579540
// One very common use case is when `streams` has two elements,
@@ -586,21 +547,39 @@ impl TokenStreamBuilder {
586547
// reallocations (#57735).
587548
let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
588549

589-
// Get the first stream. If it's `None`, create an empty
590-
// stream.
550+
// Get the first stream, which will become the result stream.
551+
// If it's `None`, create an empty stream.
591552
let mut iter = streams.drain(..);
592-
let mut first_stream_lrc = iter.next().unwrap().0;
553+
let mut res_stream_lrc = iter.next().unwrap().0;
593554

594-
// Append the elements to the first stream, after reserving
595-
// space for them.
596-
let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc);
597-
first_vec_mut.reserve(num_appends);
555+
// Append the subsequent elements to the result stream, after
556+
// reserving space for them.
557+
let res_vec_mut = Lrc::make_mut(&mut res_stream_lrc);
558+
res_vec_mut.reserve(num_appends);
598559
for stream in iter {
599-
first_vec_mut.extend(stream.0.iter().cloned());
560+
let stream_iter = stream.0.iter().cloned();
561+
562+
// If (a) `res_mut_vec` is not empty and the last tree
563+
// within it is a token tree marked with `Joint`, and (b)
564+
// `stream` is not empty and the first tree within it is a
565+
// token tree, and (c) the two tokens can be glued
566+
// together...
567+
if let Some((TokenTree::Token(last_tok), Spacing::Joint)) = res_vec_mut.last()
568+
&& let Some((TokenTree::Token(tok), spacing)) = stream.0.first()
569+
&& let Some(glued_tok) = last_tok.glue(&tok)
570+
{
571+
// ...then overwrite the last token tree in
572+
// `res_vec_mut` with the glued token, and skip the
573+
// first token tree from `stream`.
574+
*res_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
575+
res_vec_mut.extend(stream_iter.skip(1));
576+
} else {
577+
// Append all of `stream`.
578+
res_vec_mut.extend(stream_iter);
579+
}
600580
}
601581

602-
// Create the final `TokenStream`.
603-
TokenStream(first_stream_lrc)
582+
TokenStream(res_stream_lrc)
604583
}
605584
}
606585
}

0 commit comments

Comments
 (0)