Use optimized SmallVec implementation

This commit is contained in:
Igor Gutorov 2018-08-13 22:15:16 +03:00
parent e73077e106
commit 4d81fe9243
46 changed files with 156 additions and 434 deletions

View File

@ -554,7 +554,7 @@ dependencies = [
"crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1488,7 +1488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1925,6 +1925,7 @@ dependencies = [
"rustc_target 0.0.0",
"scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
"tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2086,6 +2087,7 @@ dependencies = [
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_target 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@ -2172,6 +2174,7 @@ dependencies = [
"rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_cratesio_shim 0.0.0",
"serialize 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2317,6 +2320,7 @@ dependencies = [
"rustc_errors 0.0.0",
"rustc_target 0.0.0",
"serialize 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@ -2422,6 +2426,7 @@ dependencies = [
"log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@ -2597,6 +2602,9 @@ dependencies = [
[[package]]
name = "serialize"
version = "0.0.0"
dependencies = [
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shell-escape"
@ -2615,7 +2623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.6.3"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2771,6 +2779,7 @@ dependencies = [
"rustc_target 0.0.0",
"scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax_pos 0.0.0",
]
@ -2783,6 +2792,7 @@ dependencies = [
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_target 0.0.0",
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
@ -3327,7 +3337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d"
"checksum socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "962a516af4d3a7c272cb3a1d50a8cc4e5b41802e4ad54cfb7bee8ba61d37d703"
"checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"

View File

@ -33,6 +33,7 @@ parking_lot = "0.5.5"
byteorder = { version = "1.1", features = ["i128"]}
chalk-engine = { version = "0.7.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" }
smallvec = { version = "0.6.5", features = ["union"] }
# Note that these dependencies are a lie, they're just here to get linkage to
# work.

View File

@ -12,7 +12,7 @@ use errors::DiagnosticBuilder;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use rustc_data_structures::sync::{Lrc, Lock};
use std::env;
use std::hash::Hash;
@ -1025,7 +1025,7 @@ impl CurrentDepGraph {
} = task {
debug_assert_eq!(node, key);
let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)];
self.alloc_node(node, SmallVec::one(krate_idx))
self.alloc_node(node, smallvec![krate_idx])
} else {
bug!("complete_eval_always_task() - Expected eval always task to be popped");
}

View File

@ -3178,18 +3178,18 @@ impl<'a> LoweringContext<'a> {
fn lower_item_id(&mut self, i: &Item) -> OneVector<hir::ItemId> {
match i.node {
ItemKind::Use(ref use_tree) => {
let mut vec = OneVector::one(hir::ItemId { id: i.id });
let mut vec = smallvec![hir::ItemId { id: i.id }];
self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
vec
}
ItemKind::MacroDef(..) => OneVector::new(),
ItemKind::Fn(ref decl, ref header, ..) => {
let mut ids = OneVector::one(hir::ItemId { id: i.id });
let mut ids = smallvec![hir::ItemId { id: i.id }];
self.lower_impl_trait_ids(decl, header, &mut ids);
ids
},
ItemKind::Impl(.., None, _, ref items) => {
let mut ids = OneVector::one(hir::ItemId { id: i.id });
let mut ids = smallvec![hir::ItemId { id: i.id }];
for item in items {
if let ImplItemKind::Method(ref sig, _) = item.node {
self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
@ -3197,7 +3197,7 @@ impl<'a> LoweringContext<'a> {
}
ids
},
_ => OneVector::one(hir::ItemId { id: i.id }),
_ => smallvec![hir::ItemId { id: i.id }],
}
}
@ -4297,7 +4297,7 @@ impl<'a> LoweringContext<'a> {
}
fn lower_stmt(&mut self, s: &Stmt) -> OneVector<hir::Stmt> {
OneVector::one(match s.node {
smallvec![match s.node {
StmtKind::Local(ref l) => Spanned {
node: hir::StmtKind::Decl(
P(Spanned {
@ -4336,7 +4336,7 @@ impl<'a> LoweringContext<'a> {
span: s.span,
},
StmtKind::Mac(..) => panic!("Shouldn't exist here"),
})
}]
}
fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {

View File

@ -27,7 +27,7 @@ use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt, TypeFlags};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// Canonicalizes a query value `V`. When we canonicalize a query,
@ -380,7 +380,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
// avoid allocations in those cases. We also don't use `indices` to
// determine if a kind has been seen before until the limit of 8 has
// been exceeded, to also avoid allocations for `indices`.
if var_values.is_array() {
if !var_values.spilled() {
// `var_values` is stack-allocated. `indices` isn't used yet. Do a
// direct linear search of `var_values`.
if let Some(idx) = var_values.iter().position(|&k| k == kind) {
@ -395,7 +395,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
// If `var_values` has become big enough to be heap-allocated,
// fill up `indices` to facilitate subsequent lookups.
if !var_values.is_array() {
if var_values.spilled() {
assert!(indices.is_empty());
*indices =
var_values.iter()

View File

@ -33,7 +33,7 @@
use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use rustc_data_structures::sync::Lrc;
use serialize::UseSpecializedDecodable;
use std::ops::Index;

View File

@ -109,6 +109,9 @@ extern crate rustc_apfloat;
extern crate byteorder;
extern crate backtrace;
#[macro_use]
extern crate smallvec;
// Note that librustc doesn't actually depend on these crates, see the note in
// `Cargo.toml` for this crate about why these are here.
#[allow(unused_extern_crates)]

View File

@ -24,7 +24,7 @@ use rustc_apfloat::Float;
use rustc_data_structures::graph::dominators::{dominators, Dominators};
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::ReadGuard;
use rustc_serialize as serialize;

View File

@ -10,7 +10,7 @@
use infer::at::At;
use infer::InferOk;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use std::iter::FromIterator;
use syntax::source_map::Span;
use ty::subst::Kind;

View File

@ -9,7 +9,7 @@
// except according to those terms.
use infer::InferCtxt;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use traits::{EvaluationResult, PredicateObligation, SelectionContext,
TraitQueryMode, OverflowError};

View File

@ -15,7 +15,7 @@
use infer::at::At;
use infer::{InferCtxt, InferOk};
use mir::interpret::{ConstValue, GlobalId};
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use traits::project::Normalized;
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use ty::fold::{TypeFoldable, TypeFolder};

View File

@ -11,7 +11,7 @@
use infer::InferCtxt;
use syntax::ast;
use syntax::source_map::Span;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
use traits::query::NoSolution;
use ty::{self, Ty, TyCtxt};

View File

@ -11,7 +11,7 @@
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint,
QueryResult};
use infer::{InferCtxt, InferOk};
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use std::fmt;
use std::rc::Rc;
use traits::query::Fallible;

View File

@ -9,7 +9,7 @@
// except according to those terms.
use std::mem;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use syntax::ast::CRATE_NODE_ID;
use ty::context::TyCtxt;
use ty::{DefId, DefIdTree};
@ -83,14 +83,14 @@ impl<'a, 'gcx, 'tcx> DefIdForest {
let mut next_ret = SmallVec::new();
let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
for next_forest in iter {
for id in ret.root_ids.drain(..) {
for id in ret.root_ids.drain() {
if next_forest.contains(tcx, id) {
next_ret.push(id);
} else {
old_ret.push(id);
}
}
ret.root_ids.extend(old_ret.drain(..));
ret.root_ids.extend(old_ret.drain());
for id in next_forest.root_ids {
if ret.contains(tcx, id) {
@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest {
}
mem::swap(&mut next_ret, &mut ret.root_ids);
next_ret.drain(..);
next_ret.drain();
}
ret
}
@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest {
let mut ret = DefIdForest::empty();
let mut next_ret = SmallVec::new();
for next_forest in iter {
for id in ret.root_ids.drain(..) {
for id in ret.root_ids.drain() {
if !next_forest.contains(tcx, id) {
next_ret.push(id);
}
@ -125,7 +125,7 @@ impl<'a, 'gcx, 'tcx> DefIdForest {
}
mem::swap(&mut next_ret, &mut ret.root_ids);
next_ret.drain(..);
next_ret.drain();
}
ret
}

View File

@ -55,7 +55,7 @@ use syntax::ext::hygiene::Mark;
use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
use syntax_pos::{DUMMY_SP, Span};
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
use smallvec;
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
@ -2382,7 +2382,7 @@ impl<'tcx> TyS<'tcx> {
/// Iterator that walks the immediate children of `self`. Hence
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
/// (but not `i32`, like `walk`).
pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> {
pub fn walk_shallow(&'tcx self) -> smallvec::IntoIter<walk::TypeWalkerArray<'tcx>> {
walk::walk_shallow(self)
}

View File

@ -13,8 +13,7 @@
use mir::interpret::ConstValue;
use ty::{self, Ty};
use rustc_data_structures::small_vec::SmallVec;
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
use smallvec::{self, SmallVec};
// The TypeWalker's stack is hot enough that it's worth going to some effort to
// avoid heap allocations.
@ -28,7 +27,7 @@ pub struct TypeWalker<'tcx> {
impl<'tcx> TypeWalker<'tcx> {
pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
TypeWalker { stack: SmallVec::one(ty), last_subtree: 1, }
TypeWalker { stack: smallvec![ty], last_subtree: 1, }
}
/// Skips the subtree of types corresponding to the last type
@ -67,7 +66,7 @@ impl<'tcx> Iterator for TypeWalker<'tcx> {
}
}
pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> {
pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> smallvec::IntoIter<TypeWalkerArray<'tcx>> {
let mut stack = SmallVec::new();
push_subtypes(&mut stack, ty);
stack.into_iter()

View File

@ -16,3 +16,4 @@ rustc_target = { path = "../librustc_target" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
log = "0.4"
smallvec = { version = "0.6.5", features = ["union"] }

View File

@ -78,20 +78,20 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
_ => {
self.handler
.span_err(item.span, "allocators must be statics");
return OneVector::one(item);
return smallvec![item];
}
}
if self.in_submod > 0 {
self.handler
.span_err(item.span, "`global_allocator` cannot be used in submodules");
return OneVector::one(item);
return smallvec![item];
}
if self.found {
self.handler
.span_err(item.span, "cannot define more than one #[global_allocator]");
return OneVector::one(item);
return smallvec![item];
}
self.found = true;

View File

@ -18,6 +18,8 @@ extern crate rustc_errors;
extern crate rustc_target;
extern crate syntax;
extern crate syntax_pos;
#[macro_use]
extern crate smallvec;
pub mod expand;

View File

@ -19,6 +19,7 @@ parking_lot_core = "0.2.8"
rustc-rayon = "0.1.1"
rustc-rayon-core = "0.1.1"
rustc-hash = "1.0.1"
smallvec = { version = "0.6.5", features = ["union"] }
[dependencies.parking_lot]
version = "0.5"

View File

@ -48,6 +48,8 @@ extern crate rustc_rayon as rayon;
extern crate rustc_rayon_core as rayon_core;
extern crate rustc_hash;
extern crate serialize;
#[cfg_attr(test, macro_use)]
extern crate smallvec;
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
#[allow(unused_extern_crates)]

View File

@ -16,264 +16,26 @@
//!
//! The N above is determined by Array's implementor, by way of an associated constant.
use std::ops::{Deref, DerefMut};
use std::iter::{IntoIterator, FromIterator};
use std::fmt::{self, Debug};
use std::mem;
use std::ptr;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use accumulate_vec::{IntoIter, AccumulateVec};
use array_vec::Array;
pub struct SmallVec<A: Array>(AccumulateVec<A>);
use smallvec::{Array, SmallVec};
pub type OneVector<T> = SmallVec<[T; 1]>;
impl<A> Clone for SmallVec<A>
where A: Array,
A::Element: Clone {
fn clone(&self) -> Self {
SmallVec(self.0.clone())
}
pub trait ExpectOne<A: Array> {
fn expect_one(self, err: &'static str) -> A::Item;
}
impl<A> Debug for SmallVec<A>
where A: Array + Debug,
A::Element: Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("SmallVec").field(&self.0).finish()
}
}
impl<A: Array> SmallVec<A> {
pub fn new() -> Self {
SmallVec(AccumulateVec::new())
}
pub fn is_array(&self) -> bool {
self.0.is_array()
}
pub fn with_capacity(cap: usize) -> Self {
let mut vec = SmallVec::new();
vec.reserve(cap);
vec
}
pub fn one(el: A::Element) -> Self {
SmallVec(AccumulateVec::one(el))
}
pub fn many<I: IntoIterator<Item=A::Element>>(els: I) -> Self {
SmallVec(AccumulateVec::many(els))
}
pub fn expect_one(self, err: &'static str) -> A::Element {
impl<A: Array> ExpectOne<A> for SmallVec<A> {
fn expect_one(self, err: &'static str) -> A::Item {
assert!(self.len() == 1, err);
match self.0 {
AccumulateVec::Array(arr) => arr.into_iter().next().unwrap(),
AccumulateVec::Heap(vec) => vec.into_iter().next().unwrap(),
}
}
/// Will reallocate onto the heap if needed.
pub fn push(&mut self, el: A::Element) {
self.reserve(1);
match self.0 {
AccumulateVec::Array(ref mut array) => array.push(el),
AccumulateVec::Heap(ref mut vec) => vec.push(el),
}
}
pub fn reserve(&mut self, n: usize) {
match self.0 {
AccumulateVec::Array(_) => {
if self.len() + n > A::LEN {
let len = self.len();
let array = mem::replace(&mut self.0,
AccumulateVec::Heap(Vec::with_capacity(len + n)));
if let AccumulateVec::Array(array) = array {
match self.0 {
AccumulateVec::Heap(ref mut vec) => vec.extend(array),
_ => unreachable!()
}
}
}
}
AccumulateVec::Heap(ref mut vec) => vec.reserve(n)
}
}
pub unsafe fn set_len(&mut self, len: usize) {
match self.0 {
AccumulateVec::Array(ref mut arr) => arr.set_len(len),
AccumulateVec::Heap(ref mut vec) => vec.set_len(len),
}
}
pub fn insert(&mut self, index: usize, element: A::Element) {
let len = self.len();
// Reserve space for shifting elements to the right
self.reserve(1);
assert!(index <= len);
unsafe {
// infallible
// The spot to put the new value
{
let p = self.as_mut_ptr().add(index);
// Shift everything over to make space. (Duplicating the
// `index`th element into two consecutive places.)
ptr::copy(p, p.offset(1), len - index);
// Write it in, overwriting the first copy of the `index`th
// element.
ptr::write(p, element);
}
self.set_len(len + 1);
}
}
pub fn truncate(&mut self, len: usize) {
unsafe {
while len < self.len() {
// Decrement len before the drop_in_place(), so a panic on Drop
// doesn't re-drop the just-failed value.
let newlen = self.len() - 1;
self.set_len(newlen);
::std::ptr::drop_in_place(self.get_unchecked_mut(newlen));
}
}
}
}
impl<A: Array> Deref for SmallVec<A> {
type Target = AccumulateVec<A>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<A: Array> DerefMut for SmallVec<A> {
fn deref_mut(&mut self) -> &mut AccumulateVec<A> {
&mut self.0
}
}
impl<A: Array> FromIterator<A::Element> for SmallVec<A> {
fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item=A::Element> {
SmallVec(iter.into_iter().collect())
}
}
impl<A: Array> Extend<A::Element> for SmallVec<A> {
fn extend<I: IntoIterator<Item=A::Element>>(&mut self, iter: I) {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);
match self.0 {
AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
_ => iter.for_each(|el| self.push(el))
}
}
}
impl<A: Array> IntoIterator for SmallVec<A> {
type Item = A::Element;
type IntoIter = IntoIter<A>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<A: Array> Default for SmallVec<A> {
fn default() -> SmallVec<A> {
SmallVec::new()
}
}
impl<A> Encodable for SmallVec<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() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
Ok(())
})
}
}
impl<A> Decodable for SmallVec<A>
where A: Array,
A::Element: Decodable {
fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
d.read_seq(|d, len| {
let mut vec = SmallVec::with_capacity(len);
// FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
for i in 0..len {
vec.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
}
Ok(vec)
})
self.into_iter().next().unwrap()
}
}
#[cfg(test)]
mod tests {
extern crate test;
use self::test::Bencher;
use super::*;
#[test]
fn test_len() {
let v: OneVector<isize> = OneVector::new();
assert_eq!(0, v.len());
assert_eq!(1, OneVector::one(1).len());
assert_eq!(5, OneVector::many(vec![1, 2, 3, 4, 5]).len());
}
#[test]
fn test_push_get() {
let mut v = OneVector::new();
v.push(1);
assert_eq!(1, v.len());
assert_eq!(1, v[0]);
v.push(2);
assert_eq!(2, v.len());
assert_eq!(2, v[1]);
v.push(3);
assert_eq!(3, v.len());
assert_eq!(3, v[2]);
}
#[test]
fn test_from_iter() {
let v: OneVector<isize> = (vec![1, 2, 3]).into_iter().collect();
assert_eq!(3, v.len());
assert_eq!(1, v[0]);
assert_eq!(2, v[1]);
assert_eq!(3, v[2]);
}
#[test]
fn test_move_iter() {
let v = OneVector::new();
let v: Vec<isize> = v.into_iter().collect();
assert_eq!(v, Vec::new());
let v = OneVector::one(1);
assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
let v = OneVector::many(vec![1, 2, 3]);
assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
}
#[test]
#[should_panic]
fn test_expect_one_zero() {
@ -283,120 +45,12 @@ mod tests {
#[test]
#[should_panic]
fn test_expect_one_many() {
OneVector::many(vec![1, 2]).expect_one("");
OneVector::from_vec(vec![1, 2]).expect_one("");
}
#[test]
fn test_expect_one_one() {
assert_eq!(1, OneVector::one(1).expect_one(""));
assert_eq!(1, OneVector::many(vec![1]).expect_one(""));
}
#[bench]
fn fill_small_vec_1_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(10);
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_1_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_8_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(10);
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_8_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_32_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(10);
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_32_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_1_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(50);
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_1_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_8_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(50);
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_8_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_32_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(50);
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_32_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
sv.extend(0..50);
})
assert_eq!(1, (smallvec![1] as OneVector<_>).expect_one(""));
assert_eq!(1, OneVector::from_vec(vec![1]).expect_one(""));
}
}

View File

@ -25,3 +25,4 @@ syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
byteorder = { version = "1.1", features = ["i128"] }
rustc_apfloat = { path = "../librustc_apfloat" }
smallvec = { version = "0.6.5", features = ["union"] }

View File

@ -29,7 +29,7 @@ use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_set::IdxSet;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use std::rc::Rc;

View File

@ -62,6 +62,7 @@ extern crate log_settings;
extern crate rustc_apfloat;
extern crate byteorder;
extern crate core;
extern crate smallvec;
mod diagnostics;

View File

@ -43,6 +43,7 @@ use errors::Applicability;
use std::cell::Cell;
use std::mem;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::small_vec::ExpectOne;
crate struct FromPrelude(bool);
crate struct FromExpansion(bool);

View File

@ -17,3 +17,4 @@ rustc_data_structures = { path = "../librustc_data_structures" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
chalk-engine = { version = "0.7.0", default-features=false }
smallvec = { version = "0.6.5", features = ["union"] }

View File

@ -25,7 +25,7 @@ use rustc::traits::{
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::subst::Kind;
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::small_vec::SmallVec;
use smallvec::SmallVec;
use std::fmt::{self, Debug};
use std::marker::PhantomData;

View File

@ -28,6 +28,7 @@ extern crate rustc;
extern crate rustc_data_structures;
extern crate syntax;
extern crate syntax_pos;
extern crate smallvec;
mod chalk_context;
mod dropck_outlives;

View File

@ -7,3 +7,6 @@ version = "0.0.0"
name = "serialize"
path = "lib.rs"
crate-type = ["dylib", "rlib"]
[dependencies]
smallvec = { version = "0.6.5", features = ["union"] }

View File

@ -17,6 +17,38 @@ use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSe
use std::rc::Rc;
use std::sync::Arc;
use smallvec::{Array, SmallVec};
impl<A> Encodable for SmallVec<A>
where A: Array,
A::Item: 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() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
Ok(())
})
}
}
impl<A> Decodable for SmallVec<A>
where A: Array,
A::Item: Decodable
{
fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
d.read_seq(|d, len| {
let mut vec = SmallVec::with_capacity(len);
// FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
for i in 0..len {
vec.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
}
Ok(vec)
})
}
}
impl<T: Encodable> Encodable for LinkedList<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {

View File

@ -32,6 +32,8 @@ pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder};
pub use self::serialize::{UseSpecializedEncodable, UseSpecializedDecodable};
extern crate smallvec;
mod serialize;
mod collection_impls;

View File

@ -17,3 +17,4 @@ syntax_pos = { path = "../libsyntax_pos" }
rustc_errors = { path = "../librustc_errors" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_target = { path = "../librustc_target" }
smallvec = { version = "0.6.5", features = ["union"] }

View File

@ -131,7 +131,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
let sym = Ident::with_empty_ctxt(Symbol::gensym(&format!(
"__register_diagnostic_{}", code
)));
MacEager::items(OneVector::many(vec![
MacEager::items(OneVector::from_vec(vec![
ecx.item_mod(
span,
span,
@ -214,7 +214,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
),
);
MacEager::items(OneVector::many(vec![
MacEager::items(OneVector::from_vec(vec![
P(ast::Item {
ident: *name,
attrs: Vec::new(),

View File

@ -316,11 +316,11 @@ impl<F> IdentMacroExpander for F
// Use a macro because forwarding to a simple function has type system issues
macro_rules! make_stmts_default {
($me:expr) => {
$me.make_expr().map(|e| OneVector::one(ast::Stmt {
$me.make_expr().map(|e| smallvec![ast::Stmt {
id: ast::DUMMY_NODE_ID,
span: e.span,
node: ast::StmtKind::Expr(e),
}))
}])
}
}
@ -548,11 +548,11 @@ impl MacResult for DummyResult {
}
fn make_stmts(self: Box<DummyResult>) -> Option<OneVector<ast::Stmt>> {
Some(OneVector::one(ast::Stmt {
Some(smallvec![ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)),
span: self.span,
}))
}])
}
fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {

View File

@ -37,6 +37,7 @@ use visit::{self, Visitor};
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::iter::FromIterator;
use std::{iter, mem};
use std::rc::Rc;
use std::path::PathBuf;
@ -131,7 +132,7 @@ macro_rules! ast_fragments {
self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
})*)*
$($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
self.expand_fragment(AstFragment::$Kind(OneVector::one(ast_elt))).$make_ast()
self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast()
})*)*
}
@ -270,7 +271,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let orig_mod_span = krate.module.inner;
let krate_item = AstFragment::Items(OneVector::one(P(ast::Item {
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
attrs: krate.attrs,
span: krate.span,
node: ast::ItemKind::Mod(krate.module),
@ -278,7 +279,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
id: ast::DUMMY_NODE_ID,
vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
tokens: None,
})));
})]);
match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
@ -1409,7 +1410,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
ui
});
OneVector::many(
OneVector::from_iter(
self.fold_unnameable(item).into_iter()
.chain(self.fold_unnameable(use_item)))
} else {

View File

@ -46,37 +46,37 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
match kind {
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
AstFragmentKind::Items => AstFragment::Items(OneVector::one(P(ast::Item {
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
id, span, ident, vis, attrs,
node: ast::ItemKind::Mac(mac_placeholder()),
tokens: None,
}))),
AstFragmentKind::TraitItems => AstFragment::TraitItems(OneVector::one(ast::TraitItem {
})]),
AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
id, span, ident, attrs, generics,
node: ast::TraitItemKind::Macro(mac_placeholder()),
tokens: None,
})),
AstFragmentKind::ImplItems => AstFragment::ImplItems(OneVector::one(ast::ImplItem {
}]),
AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
id, span, ident, vis, attrs, generics,
node: ast::ImplItemKind::Macro(mac_placeholder()),
defaultness: ast::Defaultness::Final,
tokens: None,
})),
}]),
AstFragmentKind::ForeignItems =>
AstFragment::ForeignItems(OneVector::one(ast::ForeignItem {
AstFragment::ForeignItems(smallvec![ast::ForeignItem {
id, span, ident, vis, attrs,
node: ast::ForeignItemKind::Macro(mac_placeholder()),
})),
}]),
AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
id, span, node: ast::PatKind::Mac(mac_placeholder()),
})),
AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
id, span, node: ast::TyKind::Mac(mac_placeholder()),
})),
AstFragmentKind::Stmts => AstFragment::Stmts(OneVector::one({
AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
})),
}]),
}
}
@ -118,7 +118,7 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
match item.node {
ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
ast::ItemKind::MacroDef(_) => return OneVector::one(item),
ast::ItemKind::MacroDef(_) => return smallvec![item],
_ => {}
}

View File

@ -644,7 +644,7 @@ pub fn parse(
// This MatcherPos instance is allocated on the stack. All others -- and
// there are frequently *no* others! -- are allocated on the heap.
let mut initial = initial_matcher_pos(ms, parser.span.lo());
let mut cur_items = OneVector::one(MatcherPosHandle::Ref(&mut initial));
let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
let mut next_items = Vec::new();
loop {

View File

@ -70,7 +70,7 @@ pub fn transcribe(cx: &ExtCtxt,
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
src: Vec<quoted::TokenTree>)
-> TokenStream {
let mut stack = OneVector::one(Frame::new(src));
let mut stack: OneVector<Frame> = smallvec![Frame::new(src)];
let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */
let mut repeats = Vec::new();
let mut result: Vec<TokenStream> = Vec::new();

View File

@ -31,6 +31,7 @@ use tokenstream::*;
use util::move_map::MoveMap;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::small_vec::ExpectOne;
pub trait Folder : Sized {
// Any additions to this trait should happen in form
@ -962,7 +963,7 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
-> OneVector<TraitItem> {
OneVector::one(TraitItem {
smallvec![TraitItem {
id: folder.new_id(i.id),
ident: folder.fold_ident(i.ident),
attrs: fold_attrs(i.attrs, folder),
@ -986,12 +987,12 @@ pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
},
span: folder.new_span(i.span),
tokens: i.tokens,
})
}]
}
pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
-> OneVector<ImplItem> {
OneVector::one(ImplItem {
smallvec![ImplItem {
id: folder.new_id(i.id),
vis: folder.fold_vis(i.vis),
ident: folder.fold_ident(i.ident),
@ -1014,7 +1015,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
},
span: folder.new_span(i.span),
tokens: i.tokens,
})
}]
}
pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> FnHeader {
@ -1067,7 +1068,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
// fold one item into possibly many items
pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> OneVector<P<Item>> {
OneVector::one(i.map(|i| folder.fold_item_simple(i)))
smallvec![i.map(|i| folder.fold_item_simple(i))]
}
// fold one item into exactly one item
@ -1089,7 +1090,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span,
pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T)
-> OneVector<ForeignItem> {
OneVector::one(folder.fold_foreign_item_simple(ni))
smallvec![folder.fold_foreign_item_simple(ni)]
}
pub fn noop_fold_foreign_item_simple<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
@ -1377,7 +1378,7 @@ pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T) ->
pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> OneVector<StmtKind> {
match node {
StmtKind::Local(local) => OneVector::one(StmtKind::Local(folder.fold_local(local))),
StmtKind::Local(local) => smallvec![StmtKind::Local(folder.fold_local(local))],
StmtKind::Item(item) => folder.fold_item(item).into_iter().map(StmtKind::Item).collect(),
StmtKind::Expr(expr) => {
folder.fold_opt_expr(expr).into_iter().map(StmtKind::Expr).collect()
@ -1385,9 +1386,9 @@ pub fn noop_fold_stmt_kind<T: Folder>(node: StmtKind, folder: &mut T) -> OneVect
StmtKind::Semi(expr) => {
folder.fold_opt_expr(expr).into_iter().map(StmtKind::Semi).collect()
}
StmtKind::Mac(mac) => OneVector::one(StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
StmtKind::Mac(mac) => smallvec![StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
(folder.fold_mac(mac), semi, fold_attrs(attrs.into(), folder).into())
}))),
}))],
}
}

View File

@ -40,6 +40,8 @@ extern crate syntax_pos;
extern crate rustc_data_structures;
extern crate rustc_target;
#[macro_use] extern crate scoped_tls;
#[macro_use]
extern crate smallvec;
extern crate serialize as rustc_serialize; // used by deriving

View File

@ -41,6 +41,7 @@ use ptr::P;
use OneVector;
use symbol::{self, Symbol, keywords};
use ThinVec;
use rustc_data_structures::small_vec::ExpectOne;
enum ShouldPanic {
No,
@ -183,7 +184,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
if ident.name != keywords::Invalid.name() {
self.cx.path.pop();
}
OneVector::one(P(item))
smallvec![P(item)]
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
@ -235,7 +236,7 @@ impl fold::Folder for EntryPointCleaner {
EntryPointType::OtherMain => folded,
};
OneVector::one(folded)
smallvec![folded]
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }

View File

@ -15,4 +15,5 @@ rustc_errors = { path = "../librustc_errors" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_target = { path = "../librustc_target" }
rustc_target = { path = "../librustc_target" }
smallvec = { version = "0.6.5", features = ["union"] }

View File

@ -18,8 +18,6 @@
/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
/// therefore apply.
use rustc_data_structures::small_vec::OneVector;
use syntax::ast;
use syntax::source_map::respan;
use syntax::ext::base;
@ -52,7 +50,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
None => return DummyResult::any(sp),
};
MacEager::items(OneVector::one(P(ast::Item {
MacEager::items(smallvec![P(ast::Item {
ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
attrs: Vec::new(),
id: ast::DUMMY_NODE_ID,
@ -63,5 +61,5 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
span: sp,
tokens: None,
})))
})])
}

View File

@ -29,6 +29,8 @@ extern crate proc_macro;
extern crate rustc_data_structures;
extern crate rustc_errors as errors;
extern crate rustc_target;
#[macro_use]
extern crate smallvec;
mod diagnostics;

View File

@ -31,7 +31,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
fn expand(cx: &mut ExtCtxt, _: syntax_pos::Span, _: &[tokenstream::TokenTree])
-> Box<MacResult+'static> {
MacEager::items(OneVector::many(vec![
MacEager::items(OneVector::from_vec(vec![
quote_item!(cx, struct Struct1;).unwrap(),
quote_item!(cx, struct Struct2;).unwrap()
]))