Skip to content

Commit

Permalink
Merge pull request #341 from dtolnay/rcvec
Browse files Browse the repository at this point in the history
Replace Rc<Vec<T>> with RcVec<T>
  • Loading branch information
dtolnay authored Jul 25, 2022
2 parents e338234 + 275aaeb commit 20eb5ed
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 23 deletions.
48 changes: 25 additions & 23 deletions src/fallback.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use crate::parse::{self, Cursor};
use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
use crate::{Delimiter, Spacing, TokenTree};
#[cfg(span_locations)]
use std::cell::RefCell;
#[cfg(span_locations)]
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.
Expand All @@ -31,7 +29,7 @@ pub fn unforce() {

#[derive(Clone)]
pub(crate) struct TokenStream {
inner: Rc<Vec<TokenTree>>,
inner: RcVec<TokenTree>,
}

#[derive(Debug)]
Expand All @@ -54,20 +52,20 @@ impl LexError {
impl TokenStream {
pub fn new() -> Self {
TokenStream {
inner: Rc::new(Vec::new()),
inner: RcVec::new(),
}
}

pub fn is_empty(&self) -> bool {
self.inner.len() == 0
}

fn take_inner(&mut self) -> Vec<TokenTree> {
mem::replace(Rc::make_mut(&mut self.inner), Vec::new())
fn take_inner(&mut self) -> RcVecBuilder<TokenTree> {
self.inner.make_mut().take()
}
}

fn push_token_from_proc_macro(vec: &mut Vec<TokenTree>, token: TokenTree) {
fn push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree) {
// https://github.com/dtolnay/proc-macro2/issues/235
match token {
#[cfg(not(no_bind_by_move_pattern_guard))]
Expand Down Expand Up @@ -98,7 +96,7 @@ fn push_token_from_proc_macro(vec: &mut Vec<TokenTree>, token: TokenTree) {
}

#[cold]
fn push_negative_literal(vec: &mut Vec<TokenTree>, mut literal: Literal) {
fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) {
literal.repr.remove(0);
let mut punct = crate::Punct::new('-', Spacing::Alone);
punct.set_span(crate::Span::_new_stable(literal.span));
Expand All @@ -110,7 +108,7 @@ fn push_token_from_proc_macro(vec: &mut Vec<TokenTree>, 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,
};
Expand All @@ -131,17 +129,19 @@ impl Drop for TokenStream {
}

pub(crate) struct TokenStreamBuilder {
inner: Vec<TokenTree>,
inner: RcVecBuilder<TokenTree>,
}

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),
}
}

Expand All @@ -151,7 +151,7 @@ impl TokenStreamBuilder {

pub fn build(self) -> TokenStream {
TokenStream {
inner: Rc::new(self.inner),
inner: self.inner.build(),
}
}
}
Expand Down Expand Up @@ -244,9 +244,11 @@ impl From<TokenStream> for proc_macro::TokenStream {

impl From<TokenTree> 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(),
}
}
}

Expand All @@ -260,32 +262,32 @@ impl FromIterator<TokenTree> for TokenStream {

impl FromIterator<TokenStream> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenStream>>(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<TokenTree> for TokenStream {
fn extend<I: IntoIterator<Item = TokenTree>>(&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<TokenStream> for TokenStream {
fn extend<I: IntoIterator<Item = TokenStream>>(&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<TokenTree>;
pub(crate) type TokenTreeIter = RcVecIntoIter<TokenTree>;

impl IntoIterator for TokenStream {
type Item = TokenTree;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ extern crate proc_macro;

mod marker;
mod parse;
mod rcvec;

#[cfg(wrap_proc_macro)]
mod detection;
Expand Down
143 changes: 143 additions & 0 deletions src/rcvec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use std::mem;
use std::rc::Rc;
use std::slice;
use std::vec;

pub(crate) struct RcVec<T> {
inner: Rc<Vec<T>>,
}

pub(crate) struct RcVecBuilder<T> {
inner: Vec<T>,
}

pub(crate) struct RcVecMut<'a, T> {
inner: &'a mut Vec<T>,
}

#[derive(Clone)]
pub(crate) struct RcVecIntoIter<T> {
inner: vec::IntoIter<T>,
}

impl<T> RcVec<T> {
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<T> {
self.inner.iter()
}

pub fn make_mut(&mut self) -> RcVecMut<T>
where
T: Clone,
{
RcVecMut {
inner: Rc::make_mut(&mut self.inner),
}
}

pub fn get_mut(&mut self) -> Option<RcVecMut<T>> {
Some(RcVecMut {
inner: Rc::get_mut(&mut self.inner)?,
})
}
}

impl<T> RcVecBuilder<T> {
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<Item = T>) {
self.inner.extend(iter);
}

pub fn as_mut(&mut self) -> RcVecMut<T> {
RcVecMut {
inner: &mut self.inner,
}
}

pub fn build(self) -> RcVec<T> {
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<Item = T>) {
self.inner.extend(iter);
}

pub fn pop(&mut self) -> Option<T> {
self.inner.pop()
}

pub fn as_mut(&mut self) -> RcVecMut<T> {
RcVecMut { inner: self.inner }
}

pub fn take(self) -> RcVecBuilder<T> {
RcVecBuilder {
inner: mem::replace(self.inner, Vec::new()),
}
}
}

impl<T> Clone for RcVec<T> {
fn clone(&self) -> Self {
RcVec {
inner: Rc::clone(&self.inner),
}
}
}

impl<T> IntoIterator for RcVecBuilder<T> {
type Item = T;
type IntoIter = RcVecIntoIter<T>;

fn into_iter(self) -> Self::IntoIter {
RcVecIntoIter {
inner: self.inner.into_iter(),
}
}
}

impl<T> Iterator for RcVecIntoIter<T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

0 comments on commit 20eb5ed

Please sign in to comment.