diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 19ac92aa66fe7..e263d11913352 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -678,7 +678,11 @@ impl TokenStream { /// Push `tt` onto the end of the stream, possibly gluing it to the last /// token. Uses `make_mut` to maximize efficiency. - pub fn push_tree(&mut self, tt: TokenTree) { + /// + /// This is intended for specific proc macro use. For general `TokenStream` + /// construction within the compiler just build a `Vec` with + /// normal `Vec` operations and then do `TokenStream::new`. + pub fn push_tree_with_gluing(&mut self, tt: TokenTree) { let vec_mut = Arc::make_mut(&mut self.0); if Self::try_glue_to_last(vec_mut, &tt) { @@ -691,7 +695,11 @@ impl TokenStream { /// Push `stream` onto the end of the stream, possibly gluing the first /// token tree to the last token. (No other token trees will be glued.) /// Uses `make_mut` to maximize efficiency. - pub fn push_stream(&mut self, stream: TokenStream) { + /// + /// This is intended for specific proc macro use. For general `TokenStream` + /// construction within the compiler just build a `Vec` with + /// normal `Vec` operations and then do `TokenStream::new`. + pub fn push_stream_with_gluing(&mut self, stream: TokenStream) { let vec_mut = Arc::make_mut(&mut self.0); let stream_iter = stream.0.iter().cloned(); diff --git a/compiler/rustc_builtin_macros/src/contracts.rs b/compiler/rustc_builtin_macros/src/contracts.rs index 52ddfbaa99f9e..e47c1b1363df0 100644 --- a/compiler/rustc_builtin_macros/src/contracts.rs +++ b/compiler/rustc_builtin_macros/src/contracts.rs @@ -48,9 +48,9 @@ fn expand_contract_clause( ecx: &mut ExtCtxt<'_>, attr_span: Span, annotated: TokenStream, - inject: impl FnOnce(&mut TokenStream) -> Result<(), ErrorGuaranteed>, + inject: impl FnOnce(&mut Vec) -> Result<(), ErrorGuaranteed>, ) -> Result { - let mut new_tts = TokenStream::default(); + let mut new_tts = vec![]; let mut cursor = annotated.iter(); let is_kw = |tt: &TokenTree, sym: Symbol| { @@ -60,7 +60,7 @@ fn expand_contract_clause( // Find the `fn` keyword to check if this is a function. if cursor .find(|tt| { - new_tts.push_tree((*tt).clone()); + new_tts.push((*tt).clone()); is_kw(tt, kw::Fn) }) .is_none() @@ -102,7 +102,7 @@ fn expand_contract_clause( if is_kw(tt, kw::Where) { break tt; } - new_tts.push_tree(tt.clone()); + new_tts.push(tt.clone()); }; // At this point, we've transcribed everything from the `fn` through the formal parameter list @@ -114,9 +114,9 @@ fn expand_contract_clause( // Above we injected the internal AST requires/ensures construct. Now copy over all the other // token trees. - new_tts.push_tree(next_tt.clone()); + new_tts.push(next_tt.clone()); while let Some(tt) = cursor.next() { - new_tts.push_tree(tt.clone()); + new_tts.push(tt.clone()); if cursor.peek().is_none() && !matches!(tt, TokenTree::Delimited(_, _, token::Delimiter::Brace, _)) { @@ -127,7 +127,7 @@ fn expand_contract_clause( } } - Ok(new_tts) + Ok(TokenStream::new(new_tts)) } fn expand_contract_clause_tts( @@ -139,11 +139,11 @@ fn expand_contract_clause_tts( ) -> Result { let feature_span = ecx.with_def_site_ctxt(attr_span); expand_contract_clause(ecx, attr_span, annotated, |new_tts| { - new_tts.push_tree(TokenTree::Token( + new_tts.push(TokenTree::Token( token::Token::from_ast_ident(Ident::new(clause_keyword, feature_span)), Spacing::Joint, )); - new_tts.push_tree(TokenTree::Delimited( + new_tts.push(TokenTree::Delimited( DelimSpan::from_single(attr_span), DelimSpacing::new(Spacing::JointHidden, Spacing::JointHidden), token::Delimiter::Brace, diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 2cf7e6abe2a24..f95a6ff767fc8 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -565,9 +565,12 @@ fn transcribe_pnr<'tx>( let leading_if_span = guard.span_with_leading_if.with_hi(guard.span_with_leading_if.lo() + BytePos(2)); - let mut ts = - TokenStream::token_alone(token::Ident(kw::If, IdentIsRaw::No), leading_if_span); - ts.push_stream(TokenStream::from_ast(&guard.cond)); + let ts = std::iter::once(TokenTree::token_alone( + token::Ident(kw::If, IdentIsRaw::No), + leading_if_span, + )) + .chain(TokenStream::from_ast(&guard.cond).iter().cloned()) + .collect(); mk_delimited(guard.span_with_leading_if, MetaVarKind::Guard, ts) } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 65af690611919..5367de7a1cc82 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -663,7 +663,7 @@ impl server::Server for Rustc<'_, '_> { let mut stream = base.unwrap_or_default(); for tree in trees { for tt in (tree, &mut *self).to_internal() { - stream.push_tree(tt); + stream.push_tree_with_gluing(tt); } } stream @@ -676,7 +676,7 @@ impl server::Server for Rustc<'_, '_> { ) -> Self::TokenStream { let mut stream = base.unwrap_or_default(); for s in streams { - stream.push_stream(s); + stream.push_stream_with_gluing(s); } stream } diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs index b54fdf6d8eaf8..d8c4ff3e9aaf7 100644 --- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs +++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs @@ -25,8 +25,8 @@ fn test_concat() { let test_fst = string_to_ts("foo::bar"); let test_snd = string_to_ts("::baz"); let mut eq_res = TokenStream::default(); - eq_res.push_stream(test_fst); - eq_res.push_stream(test_snd); + eq_res.push_stream_with_gluing(test_fst); + eq_res.push_stream_with_gluing(test_snd); assert_eq!(test_res.iter().count(), 5); assert_eq!(eq_res.iter().count(), 5); assert_eq!(cmp_token_stream(&test_res, &eq_res), true); @@ -105,9 +105,9 @@ fn test_is_empty() { fn test_dotdotdot() { create_default_session_globals_then(|| { let mut stream = TokenStream::default(); - stream.push_tree(TokenTree::token_joint(token::Dot, sp(0, 1))); - stream.push_tree(TokenTree::token_joint(token::Dot, sp(1, 2))); - stream.push_tree(TokenTree::token_alone(token::Dot, sp(2, 3))); + stream.push_tree_with_gluing(TokenTree::token_joint(token::Dot, sp(0, 1))); + stream.push_tree_with_gluing(TokenTree::token_joint(token::Dot, sp(1, 2))); + stream.push_tree_with_gluing(TokenTree::token_alone(token::Dot, sp(2, 3))); assert!(cmp_token_stream(&stream, &string_to_ts("..."))); assert_eq!(stream.iter().count(), 1); })