Make TokenTree::uninterpolate take &self and return a Cow.

Making it similar to `Token::uninterpolate`. This avoids some more token
tree cloning.
This commit is contained in:
Nicholas Nethercote 2023-07-27 10:10:32 +10:00
parent 103bd4a820
commit 55a732461d
2 changed files with 14 additions and 12 deletions

View File

@ -290,12 +290,12 @@ impl MetaItem {
I: Iterator<Item = &'a TokenTree>, I: Iterator<Item = &'a TokenTree>,
{ {
// FIXME: Share code with `parse_path`. // FIXME: Share code with `parse_path`.
let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt.clone())) { let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() {
Some(TokenTree::Token( Some(&TokenTree::Token(
Token { kind: kind @ (token::Ident(..) | token::ModSep), span }, Token { kind: ref kind @ (token::Ident(..) | token::ModSep), span },
_, _,
)) => 'arm: { )) => 'arm: {
let mut segments = if let token::Ident(name, _) = kind { let mut segments = if let &token::Ident(name, _) = kind {
if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) = if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
tokens.peek() tokens.peek()
{ {
@ -308,8 +308,8 @@ impl MetaItem {
thin_vec![PathSegment::path_root(span)] thin_vec![PathSegment::path_root(span)]
}; };
loop { loop {
if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) = if let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
tokens.next().map(|tt| TokenTree::uninterpolate(tt.clone())) tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref()
{ {
segments.push(PathSegment::from_ident(Ident::new(name, span))); segments.push(PathSegment::from_ident(Ident::new(name, span)));
} else { } else {
@ -326,7 +326,7 @@ impl MetaItem {
let span = span.with_hi(segments.last().unwrap().ident.span.hi()); let span = span.with_hi(segments.last().unwrap().ident.span.hi());
Path { span, segments, tokens: None } Path { span, segments, tokens: None }
} }
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &*nt { Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt {
token::Nonterminal::NtMeta(item) => return item.meta(item.path.span), token::Nonterminal::NtMeta(item) => return item.meta(item.path.span),
token::Nonterminal::NtPath(path) => (**path).clone(), token::Nonterminal::NtPath(path) => (**path).clone(),
_ => return None, _ => return None,

View File

@ -25,6 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::borrow::Cow;
use std::{fmt, iter, mem}; use std::{fmt, iter, mem};
/// When the main Rust parser encounters a syntax-extension invocation, it /// When the main Rust parser encounters a syntax-extension invocation, it
@ -98,12 +99,13 @@ impl TokenTree {
TokenTree::Token(Token::new(kind, span), Spacing::Joint) TokenTree::Token(Token::new(kind, span), Spacing::Joint)
} }
pub fn uninterpolate(self) -> TokenTree { pub fn uninterpolate(&self) -> Cow<'_, TokenTree> {
match self { match self {
TokenTree::Token(token, spacing) => { TokenTree::Token(token, spacing) => match token.uninterpolate() {
TokenTree::Token(token.uninterpolate().into_owned(), spacing) Cow::Owned(token) => Cow::Owned(TokenTree::Token(token, *spacing)),
} Cow::Borrowed(_) => Cow::Borrowed(self),
tt => tt, },
_ => Cow::Borrowed(self),
} }
} }
} }