Skip to content

Commit 1add4de

Browse files
committed
auto merge of #17920 : thestinger/rust/vec, r=aturon
Introduce conversions between `Box<[T]>` and `Vec<T>` and use it to reimplement the `vec![]` macro for efficiency.
2 parents 78a7676 + 02d976a commit 1add4de

File tree

6 files changed

+60
-15
lines changed

6 files changed

+60
-15
lines changed

src/libcollections/slice.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
8888
#![doc(primitive = "slice")]
8989

90+
use alloc::boxed::Box;
9091
use core::cmp;
9192
use core::mem::size_of;
9293
use core::mem;
@@ -298,6 +299,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
298299
fn into_vec(self) -> Vec<T> { self.to_vec() }
299300
}
300301

302+
#[experimental]
303+
pub trait BoxedSlice<T> {
304+
/// Convert `self` into a vector without clones or allocation.
305+
fn into_vec(self) -> Vec<T>;
306+
}
307+
308+
impl<T> BoxedSlice<T> for Box<[T]> {
309+
#[experimental]
310+
fn into_vec(mut self) -> Vec<T> {
311+
unsafe {
312+
let xs = Vec::from_raw_parts(self.len(), self.len(), self.as_mut_ptr());
313+
mem::forget(self);
314+
xs
315+
}
316+
}
317+
}
318+
301319
/// Extension methods for vectors containing `Clone` elements.
302320
pub trait ImmutableCloneableVector<T> {
303321
/// Partitions the vector into two vectors `(a, b)`, where all
@@ -2308,6 +2326,13 @@ mod tests {
23082326
let y: &mut [int] = [];
23092327
assert!(y.last_mut().is_none());
23102328
}
2329+
2330+
#[test]
2331+
fn test_into_vec() {
2332+
let xs = box [1u, 2, 3];
2333+
let ys = xs.into_vec();
2334+
assert_eq!(ys.as_slice(), [1u, 2, 3].as_slice());
2335+
}
23112336
}
23122337

23132338
#[cfg(test)]

src/libcollections/vec.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
1515
use core::prelude::*;
1616

17+
use alloc::boxed::Box;
1718
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
1819
use core::cmp::max;
1920
use core::default::Default;
@@ -757,6 +758,20 @@ impl<T> Vec<T> {
757758
}
758759
}
759760

761+
/// Convert the vector into Box<[T]>.
762+
///
763+
/// Note that this will drop any excess capacity. Calling this and converting back to a vector
764+
/// with `into_vec()` is equivalent to calling `shrink_to_fit()`.
765+
#[experimental]
766+
pub fn into_boxed_slice(mut self) -> Box<[T]> {
767+
self.shrink_to_fit();
768+
unsafe {
769+
let xs: Box<[T]> = mem::transmute(self.as_mut_slice());
770+
mem::forget(self);
771+
xs
772+
}
773+
}
774+
760775
/// Deprecated, call `push` instead
761776
#[inline]
762777
#[deprecated = "call .push() instead"]
@@ -1734,7 +1749,7 @@ impl<T> MutableSeq<T> for Vec<T> {
17341749
let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
17351750
if old_size > size { fail!("capacity overflow") }
17361751
unsafe {
1737-
self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::<T>(), size);
1752+
self.ptr = alloc_or_realloc(self.ptr, old_size, size);
17381753
}
17391754
self.cap = max(self.cap, 2) * 2;
17401755
}
@@ -1758,7 +1773,6 @@ impl<T> MutableSeq<T> for Vec<T> {
17581773
}
17591774
}
17601775
}
1761-
17621776
}
17631777

17641778
/// An iterator that moves out of a vector.
@@ -2632,6 +2646,13 @@ mod tests {
26322646
assert!(vec2 == vec!((), (), ()));
26332647
}
26342648

2649+
#[test]
2650+
fn test_into_boxed_slice() {
2651+
let xs = vec![1u, 2, 3];
2652+
let ys = xs.into_boxed_slice();
2653+
assert_eq!(ys.as_slice(), [1u, 2, 3].as_slice());
2654+
}
2655+
26352656
#[bench]
26362657
fn bench_new(b: &mut Bencher) {
26372658
b.iter(|| {

src/libstd/io/net/tcp.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
//! listener (socket server) implements the `Listener` and `Acceptor` traits.
1919
2020
use clone::Clone;
21-
use collections::MutableSeq;
2221
use io::IoResult;
2322
use iter::Iterator;
2423
use slice::ImmutableSlice;

src/libstd/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,9 @@ mod std {
272272
// The test runner calls ::std::os::args() but really wants realstd
273273
#[cfg(test)] pub use realstd::os as os;
274274
// The test runner requires std::slice::Vector, so re-export std::slice just for it.
275-
#[cfg(test)] pub use slice;
275+
//
276+
// It is also used in vec![]
277+
pub use slice;
276278

277-
pub use collections; // vec!() uses MutableSeq
279+
pub use boxed; // used for vec![]
278280
}

src/libstd/macros.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,14 @@ macro_rules! try(
323323

324324
/// Create a `std::vec::Vec` containing the arguments.
325325
#[macro_export]
326-
macro_rules! vec(
327-
($($e:expr),*) => ({
328-
// leading _ to allow empty construction without a warning.
329-
let mut _temp = ::std::vec::Vec::new();
330-
$(_temp.push($e);)*
331-
_temp
326+
macro_rules! vec[
327+
($($x:expr),*) => ({
328+
use std::slice::BoxedSlice;
329+
let xs: ::std::boxed::Box<[_]> = box [$($x),*];
330+
xs.into_vec()
332331
});
333-
($($e:expr),+,) => (vec!($($e),+))
334-
)
335-
332+
($($x:expr,)*) => (vec![$($x),*])
333+
]
336334

337335
/// A macro to select an event from a number of receivers.
338336
///

src/libstd/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
8989
#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
9090
#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
91-
#[doc(no_inline)] pub use slice::{AsSlice, VectorVector};
91+
#[doc(no_inline)] pub use slice::{AsSlice, VectorVector, BoxedSlice};
9292
#[doc(no_inline)] pub use slice::MutableSliceAllocating;
9393
#[doc(no_inline)] pub use string::String;
9494
#[doc(no_inline)] pub use vec::Vec;

0 commit comments

Comments
 (0)