Skip to content

Commit

Permalink
Rollup merge of rust-lang#37551 - Mark-Simulacrum:upgrade-accvec, r=e…
Browse files Browse the repository at this point in the history
…ddyb

Replace syntax's SmallVector with AccumulateVec

This adds a new type to data_structures, `SmallVec`, which wraps `AccumulateVec` with support for re-allocating onto the heap (`SmallVec::reserve`). `SmallVec` is then used to replace the implementation of `SmallVector` in libsyntax.

r? @eddyb

Fixes rust-lang#37371. Using `SmallVec` instead of libsyntax's `SmallVector` will provide the `N = 2/4` case easily (just needs a few more `Array` impls).

cc @nnethercote, probably interested in this area
  • Loading branch information
eddyb committed Nov 12, 2016
2 parents c3ab57c + 7bbebb1 commit f19f939
Show file tree
Hide file tree
Showing 15 changed files with 573 additions and 286 deletions.
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ DEPS_serialize := std log
DEPS_term := std
DEPS_test := std getopts term native:rust_test_helpers

DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode rustc_errors syntax_pos
DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode rustc_errors syntax_pos rustc_data_structures
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
DEPS_syntax_pos := serialize
DEPS_proc_macro_tokens := syntax syntax_pos log
Expand Down
1 change: 1 addition & 0 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
{
// We use SmallVector here instead of Vec because this code is hot and
// it's rare that the stack length exceeds 1.
let mut stack = SmallVector::zero();
let mut stack = SmallVector::new();
stack.push((a_ty, dir, b_vid));
loop {
// For each turn of the loop, we extract a tuple
Expand Down
158 changes: 152 additions & 6 deletions src/librustc_data_structures/accumulate_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,68 @@
//! A vector type intended to be used for collecting from iterators onto the stack.
//!
//! Space for up to N elements is provided on the stack. If more elements are collected, Vec is
//! used to store the values on the heap. This type does not support re-allocating onto the heap,
//! and there is no way to push more elements onto the existing storage.
//! used to store the values on the heap.
//!
//! The N above is determined by Array's implementor, by way of an associatated constant.

use std::ops::Deref;
use std::iter::{IntoIterator, FromIterator};
use std::ops::{Deref, DerefMut};
use std::iter::{self, IntoIterator, FromIterator};
use std::slice;
use std::vec;

use array_vec::{Array, ArrayVec};
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

#[derive(Debug)]
use array_vec::{self, Array, ArrayVec};

#[derive(PartialEq, Eq, Hash, Debug)]
pub enum AccumulateVec<A: Array> {
Array(ArrayVec<A>),
Heap(Vec<A::Element>)
}

impl<A> Clone for AccumulateVec<A>
where A: Array,
A::Element: Clone {
fn clone(&self) -> Self {
match *self {
AccumulateVec::Array(ref arr) => AccumulateVec::Array(arr.clone()),
AccumulateVec::Heap(ref vec) => AccumulateVec::Heap(vec.clone()),
}
}
}

impl<A: Array> AccumulateVec<A> {
pub fn new() -> AccumulateVec<A> {
AccumulateVec::Array(ArrayVec::new())
}

pub fn one(el: A::Element) -> Self {
iter::once(el).collect()
}

pub fn many<I: IntoIterator<Item=A::Element>>(iter: I) -> Self {
iter.into_iter().collect()
}

pub fn len(&self) -> usize {
match *self {
AccumulateVec::Array(ref arr) => arr.len(),
AccumulateVec::Heap(ref vec) => vec.len(),
}
}

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

pub fn pop(&mut self) -> Option<A::Element> {
match *self {
AccumulateVec::Array(ref mut arr) => arr.pop(),
AccumulateVec::Heap(ref mut vec) => vec.pop(),
}
}
}

impl<A: Array> Deref for AccumulateVec<A> {
type Target = [A::Element];
fn deref(&self) -> &Self::Target {
Expand All @@ -37,6 +83,15 @@ impl<A: Array> Deref for AccumulateVec<A> {
}
}

impl<A: Array> DerefMut for AccumulateVec<A> {
fn deref_mut(&mut self) -> &mut [A::Element] {
match *self {
AccumulateVec::Array(ref mut v) => &mut v[..],
AccumulateVec::Heap(ref mut v) => &mut v[..],
}
}
}

impl<A: Array> FromIterator<A::Element> for AccumulateVec<A> {
fn from_iter<I>(iter: I) -> AccumulateVec<A> where I: IntoIterator<Item=A::Element> {
let iter = iter.into_iter();
Expand All @@ -50,3 +105,94 @@ impl<A: Array> FromIterator<A::Element> for AccumulateVec<A> {
}
}

pub struct IntoIter<A: Array> {
repr: IntoIterRepr<A>,
}

enum IntoIterRepr<A: Array> {
Array(array_vec::Iter<A>),
Heap(vec::IntoIter<A::Element>),
}

impl<A: Array> Iterator for IntoIter<A> {
type Item = A::Element;

fn next(&mut self) -> Option<A::Element> {
match self.repr {
IntoIterRepr::Array(ref mut arr) => arr.next(),
IntoIterRepr::Heap(ref mut iter) => iter.next(),
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
match self.repr {
IntoIterRepr::Array(ref iter) => iter.size_hint(),
IntoIterRepr::Heap(ref iter) => iter.size_hint(),
}
}
}

impl<A: Array> IntoIterator for AccumulateVec<A> {
type Item = A::Element;
type IntoIter = IntoIter<A>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
repr: match self {
AccumulateVec::Array(arr) => IntoIterRepr::Array(arr.into_iter()),
AccumulateVec::Heap(vec) => IntoIterRepr::Heap(vec.into_iter()),
}
}
}
}

impl<'a, A: Array> IntoIterator for &'a AccumulateVec<A> {
type Item = &'a A::Element;
type IntoIter = slice::Iter<'a, A::Element>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

impl<'a, A: Array> IntoIterator for &'a mut AccumulateVec<A> {
type Item = &'a mut A::Element;
type IntoIter = slice::IterMut<'a, A::Element>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}

impl<A: Array> From<Vec<A::Element>> for AccumulateVec<A> {
fn from(v: Vec<A::Element>) -> AccumulateVec<A> {
AccumulateVec::many(v)
}
}

impl<A: Array> Default for AccumulateVec<A> {
fn default() -> AccumulateVec<A> {
AccumulateVec::new()
}
}

impl<A> Encodable for AccumulateVec<A>
where A: Array,
A::Element: Encodable {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
try!(s.emit_seq_elt(i, |s| e.encode(s)));
}
Ok(())
})
}
}

impl<A> Decodable for AccumulateVec<A>
where A: Array,
A::Element: Decodable {
fn decode<D: Decoder>(d: &mut D) -> Result<AccumulateVec<A>, D::Error> {
d.read_seq(|d, len| {
Ok(try!((0..len).map(|i| d.read_seq_elt(i, |d| Decodable::decode(d))).collect()))
})
}
}

Loading

0 comments on commit f19f939

Please sign in to comment.