From 275aaeb76b03020fc5fc9b1e321c910f7c4b9c68 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 25 Jul 2022 10:25:33 -0700 Subject: [PATCH] Replace Rc> with RcVec --- src/fallback.rs | 48 ++++++++-------- src/lib.rs | 1 + src/rcvec.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 23 deletions(-) create mode 100644 src/rcvec.rs diff --git a/src/fallback.rs b/src/fallback.rs index 37300845..80cea94b 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -1,4 +1,5 @@ use crate::parse::{self, Cursor}; +use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut}; use crate::{Delimiter, Spacing, TokenTree}; #[cfg(span_locations)] use std::cell::RefCell; @@ -6,14 +7,11 @@ use std::cell::RefCell; use std::cmp; use std::fmt::{self, Debug, Display, Write}; use std::iter::FromIterator; -use std::mem; use std::ops::RangeBounds; #[cfg(procmacro2_semver_exempt)] use std::path::Path; use std::path::PathBuf; -use std::rc::Rc; use std::str::FromStr; -use std::vec; /// Force use of proc-macro2's fallback implementation of the API for now, even /// if the compiler's implementation is available. @@ -31,7 +29,7 @@ pub fn unforce() { #[derive(Clone)] pub(crate) struct TokenStream { - inner: Rc>, + inner: RcVec, } #[derive(Debug)] @@ -54,7 +52,7 @@ impl LexError { impl TokenStream { pub fn new() -> Self { TokenStream { - inner: Rc::new(Vec::new()), + inner: RcVec::new(), } } @@ -62,12 +60,12 @@ impl TokenStream { self.inner.len() == 0 } - fn take_inner(&mut self) -> Vec { - mem::replace(Rc::make_mut(&mut self.inner), Vec::new()) + fn take_inner(&mut self) -> RcVecBuilder { + self.inner.make_mut().take() } } -fn push_token_from_proc_macro(vec: &mut Vec, token: TokenTree) { +fn push_token_from_proc_macro(mut vec: RcVecMut, token: TokenTree) { // https://github.com/dtolnay/proc-macro2/issues/235 match token { #[cfg(not(no_bind_by_move_pattern_guard))] @@ -98,7 +96,7 @@ fn push_token_from_proc_macro(vec: &mut Vec, token: TokenTree) { } #[cold] - fn push_negative_literal(vec: &mut Vec, mut literal: Literal) { + fn push_negative_literal(mut vec: RcVecMut, mut literal: Literal) { literal.repr.remove(0); let mut punct = crate::Punct::new('-', Spacing::Alone); punct.set_span(crate::Span::_new_stable(literal.span)); @@ -110,7 +108,7 @@ fn push_token_from_proc_macro(vec: &mut Vec, token: TokenTree) { // Nonrecursive to prevent stack overflow. impl Drop for TokenStream { fn drop(&mut self) { - let inner = match Rc::get_mut(&mut self.inner) { + let mut inner = match self.inner.get_mut() { Some(inner) => inner, None => return, }; @@ -131,17 +129,19 @@ impl Drop for TokenStream { } pub(crate) struct TokenStreamBuilder { - inner: Vec, + inner: RcVecBuilder, } impl TokenStreamBuilder { pub fn new() -> Self { - TokenStreamBuilder { inner: Vec::new() } + TokenStreamBuilder { + inner: RcVecBuilder::new(), + } } pub fn with_capacity(cap: usize) -> Self { TokenStreamBuilder { - inner: Vec::with_capacity(cap), + inner: RcVecBuilder::with_capacity(cap), } } @@ -151,7 +151,7 @@ impl TokenStreamBuilder { pub fn build(self) -> TokenStream { TokenStream { - inner: Rc::new(self.inner), + inner: self.inner.build(), } } } @@ -244,9 +244,11 @@ impl From for proc_macro::TokenStream { impl From for TokenStream { fn from(tree: TokenTree) -> TokenStream { - let mut stream = TokenStreamBuilder::new(); - push_token_from_proc_macro(&mut stream.inner, tree); - stream.build() + let mut stream = RcVecBuilder::new(); + push_token_from_proc_macro(stream.as_mut(), tree); + TokenStream { + inner: stream.build(), + } } } @@ -260,32 +262,32 @@ impl FromIterator for TokenStream { impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { - let mut v = Vec::new(); + let mut v = RcVecBuilder::new(); for mut stream in streams { v.extend(stream.take_inner()); } - TokenStream { inner: Rc::new(v) } + TokenStream { inner: v.build() } } } impl Extend for TokenStream { fn extend>(&mut self, tokens: I) { - let vec = Rc::make_mut(&mut self.inner); + let mut vec = self.inner.make_mut(); tokens .into_iter() - .for_each(|token| push_token_from_proc_macro(vec, token)); + .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token)); } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { - Rc::make_mut(&mut self.inner).extend(streams.into_iter().flatten()); + self.inner.make_mut().extend(streams.into_iter().flatten()); } } -pub(crate) type TokenTreeIter = vec::IntoIter; +pub(crate) type TokenTreeIter = RcVecIntoIter; impl IntoIterator for TokenStream { type Item = TokenTree; diff --git a/src/lib.rs b/src/lib.rs index 5a1c4e1b..8e417f79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,6 +120,7 @@ extern crate proc_macro; mod marker; mod parse; +mod rcvec; #[cfg(wrap_proc_macro)] mod detection; diff --git a/src/rcvec.rs b/src/rcvec.rs new file mode 100644 index 00000000..ad00c43e --- /dev/null +++ b/src/rcvec.rs @@ -0,0 +1,143 @@ +use std::mem; +use std::rc::Rc; +use std::slice; +use std::vec; + +pub(crate) struct RcVec { + inner: Rc>, +} + +pub(crate) struct RcVecBuilder { + inner: Vec, +} + +pub(crate) struct RcVecMut<'a, T> { + inner: &'a mut Vec, +} + +#[derive(Clone)] +pub(crate) struct RcVecIntoIter { + inner: vec::IntoIter, +} + +impl RcVec { + pub fn new() -> Self { + RcVec { + inner: Rc::new(Vec::new()), + } + } + + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + pub fn len(&self) -> usize { + self.inner.len() + } + + pub fn iter(&self) -> slice::Iter { + self.inner.iter() + } + + pub fn make_mut(&mut self) -> RcVecMut + where + T: Clone, + { + RcVecMut { + inner: Rc::make_mut(&mut self.inner), + } + } + + pub fn get_mut(&mut self) -> Option> { + Some(RcVecMut { + inner: Rc::get_mut(&mut self.inner)?, + }) + } +} + +impl RcVecBuilder { + pub fn new() -> Self { + RcVecBuilder { inner: Vec::new() } + } + + pub fn with_capacity(cap: usize) -> Self { + RcVecBuilder { + inner: Vec::with_capacity(cap), + } + } + + pub fn push(&mut self, element: T) { + self.inner.push(element); + } + + pub fn extend(&mut self, iter: impl IntoIterator) { + self.inner.extend(iter); + } + + pub fn as_mut(&mut self) -> RcVecMut { + RcVecMut { + inner: &mut self.inner, + } + } + + pub fn build(self) -> RcVec { + RcVec { + inner: Rc::new(self.inner), + } + } +} + +impl<'a, T> RcVecMut<'a, T> { + pub fn push(&mut self, element: T) { + self.inner.push(element); + } + + pub fn extend(&mut self, iter: impl IntoIterator) { + self.inner.extend(iter); + } + + pub fn pop(&mut self) -> Option { + self.inner.pop() + } + + pub fn as_mut(&mut self) -> RcVecMut { + RcVecMut { inner: self.inner } + } + + pub fn take(self) -> RcVecBuilder { + RcVecBuilder { + inner: mem::replace(self.inner, Vec::new()), + } + } +} + +impl Clone for RcVec { + fn clone(&self) -> Self { + RcVec { + inner: Rc::clone(&self.inner), + } + } +} + +impl IntoIterator for RcVecBuilder { + type Item = T; + type IntoIter = RcVecIntoIter; + + fn into_iter(self) -> Self::IntoIter { + RcVecIntoIter { + inner: self.inner.into_iter(), + } + } +} + +impl Iterator for RcVecIntoIter { + type Item = T; + + fn next(&mut self) -> Option { + self.inner.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +}