about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Turon <aturon@mozilla.com>2014-12-17 20:50:16 -0800
committerAaron Turon <aturon@mozilla.com>2014-12-30 12:02:22 -0800
commit4f863a338e0a7c33f81a8ac138103f1a0e8b33c5 (patch)
treed4c5e6fa5c8cf9468d24b8927b94307425b1a2c5
parent9d919d2302b5df42e3bf8979560e0da21f4b2bad (diff)
downloadrust-4f863a338e0a7c33f81a8ac138103f1a0e8b33c5.tar.gz
rust-4f863a338e0a7c33f81a8ac138103f1a0e8b33c5.zip
Second pass stabilization: slice
This commit takes a second pass through the `slice` module to
stabilize its API. The changes are as follows:

**Stable**:

* `as_mut_slice`
* `as_ptr`, `as_mut_ptr`
* `binary_search_by` (was: `binary_search`)
* `binary_search` (was: `binary_search_elem`)
* `chunks`, `chunks_mut`
* `contains`
* `ends_with`
* `first`, `first_mut` (was: `head`)
* `get_unchecked`, `get_unchecked_mut` (was: `unsafe_get`)
* `get`
* `is_empty`
* `iter`, `iter_mut`
* `len`
* `reverse`
* `sort_by`
* `sort`
* `split_at`, `split_at_mut`
* `split_mut`, `splitn_mut`, `rsplitn_mut`
* `split`, `splitn`, `rsplitn`
* `starts_with`
* `swap`
* `to_vec`
* `windows`

**Deprecated**:

* `head`, `head_mut` (renamed as above)
* `unsafe_get`, `unsafe_mut` (renamed as above)
* `binary_search_elem` (renamed as above)
* `partitioned`, deprecated in favor of a new, more
  general iterator consumer called `partition`.
* `BinarySearchResult`, deprecated in favor of `Result<uint, uint>`

[breaking-change]
-rw-r--r--src/libcollections/slice.rs1380
-rw-r--r--src/libcore/slice.rs328
m---------src/rust-installer0
3 files changed, 886 insertions, 822 deletions
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index c55a8ba104e..ec522ae9e5a 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -96,601 +96,26 @@ use core::mem::size_of;
 use core::mem;
 use core::ops::{FnMut,SliceMut};
 use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option};
-use core::prelude::{Ord, Ordering, PtrExt, Some, range};
+use core::prelude::{Ord, Ordering, RawPtr, Some, range, IteratorCloneExt, Result};
 use core::ptr;
 use core::slice as core_slice;
 use self::Direction::*;
 
 use vec::Vec;
 
-pub use core::slice::{Chunks, AsSlice, SplitsN, Windows};
+pub use core::slice::{Chunks, AsSlice, SplitN, Windows};
 pub use core::slice::{Iter, IterMut, PartialEqSliceExt};
-pub use core::slice::{ImmutableIntSlice, MutableIntSlice};
-pub use core::slice::{MutSplits, MutChunks, Splits};
+pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
+pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
-pub use core::slice::{from_raw_buf, from_raw_mut_buf, BinarySearchResult};
+pub use core::slice::{from_raw_buf, from_raw_mut_buf};
 
-// Functional utilities
-
-#[allow(missing_docs)]
-pub trait VectorVector<T> for Sized? {
-    // FIXME #5898: calling these .concat and .connect conflicts with
-    // StrVector::con{cat,nect}, since they have generic contents.
-    /// Flattens a vector of vectors of `T` into a single `Vec<T>`.
-    fn concat_vec(&self) -> Vec<T>;
-
-    /// Concatenate a vector of vectors, placing a given separator between each.
-    fn connect_vec(&self, sep: &T) -> Vec<T>;
-}
-
-impl<'a, T: Clone, V: AsSlice<T>> VectorVector<T> for [V] {
-    fn concat_vec(&self) -> Vec<T> {
-        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
-        let mut result = Vec::with_capacity(size);
-        for v in self.iter() {
-            result.push_all(v.as_slice())
-        }
-        result
-    }
-
-    fn connect_vec(&self, sep: &T) -> Vec<T> {
-        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
-        let mut result = Vec::with_capacity(size + self.len());
-        let mut first = true;
-        for v in self.iter() {
-            if first { first = false } else { result.push(sep.clone()) }
-            result.push_all(v.as_slice())
-        }
-        result
-    }
-}
-
-/// An iterator that yields the element swaps needed to produce
-/// a sequence of all possible permutations for an indexed sequence of
-/// elements. Each permutation is only a single swap apart.
-///
-/// The Steinhaus-Johnson-Trotter algorithm is used.
-///
-/// Generates even and odd permutations alternately.
-///
-/// The last generated swap is always (0, 1), and it returns the
-/// sequence to its initial order.
-pub struct ElementSwaps {
-    sdir: Vec<SizeDirection>,
-    /// If `true`, emit the last swap that returns the sequence to initial
-    /// state.
-    emit_reset: bool,
-    swaps_made : uint,
-}
-
-impl ElementSwaps {
-    /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
-    pub fn new(length: uint) -> ElementSwaps {
-        // Initialize `sdir` with a direction that position should move in
-        // (all negative at the beginning) and the `size` of the
-        // element (equal to the original index).
-        ElementSwaps{
-            emit_reset: true,
-            sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
-            swaps_made: 0
-        }
-    }
-}
-
-#[deriving(Copy)]
-enum Direction { Pos, Neg }
-
-/// An `Index` and `Direction` together.
-#[deriving(Copy)]
-struct SizeDirection {
-    size: uint,
-    dir: Direction,
-}
-
-impl Iterator<(uint, uint)> for ElementSwaps {
-    #[inline]
-    fn next(&mut self) -> Option<(uint, uint)> {
-        fn new_pos(i: uint, s: Direction) -> uint {
-            i + match s { Pos => 1, Neg => -1 }
-        }
-
-        // Find the index of the largest mobile element:
-        // The direction should point into the vector, and the
-        // swap should be with a smaller `size` element.
-        let max = self.sdir.iter().map(|&x| x).enumerate()
-                           .filter(|&(i, sd)|
-                                new_pos(i, sd.dir) < self.sdir.len() &&
-                                self.sdir[new_pos(i, sd.dir)].size < sd.size)
-                           .max_by(|&(_, sd)| sd.size);
-        match max {
-            Some((i, sd)) => {
-                let j = new_pos(i, sd.dir);
-                self.sdir.swap(i, j);
-
-                // Swap the direction of each larger SizeDirection
-                for x in self.sdir.iter_mut() {
-                    if x.size > sd.size {
-                        x.dir = match x.dir { Pos => Neg, Neg => Pos };
-                    }
-                }
-                self.swaps_made += 1;
-                Some((i, j))
-            },
-            None => if self.emit_reset {
-                self.emit_reset = false;
-                if self.sdir.len() > 1 {
-                    // The last swap
-                    self.swaps_made += 1;
-                    Some((0, 1))
-                } else {
-                    // Vector is of the form [] or [x], and the only permutation is itself
-                    self.swaps_made += 1;
-                    Some((0,0))
-                }
-            } else { None }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        // For a vector of size n, there are exactly n! permutations.
-        let n = range(2, self.sdir.len() + 1).product();
-        (n - self.swaps_made, Some(n - self.swaps_made))
-    }
-}
-
-/// An iterator that uses `ElementSwaps` to iterate through
-/// all possible permutations of a vector.
-///
-/// The first iteration yields a clone of the vector as it is,
-/// then each successive element is the vector with one
-/// swap applied.
-///
-/// Generates even and odd permutations alternately.
-pub struct Permutations<T> {
-    swaps: ElementSwaps,
-    v: Vec<T>,
-}
-
-impl<T: Clone> Iterator<Vec<T>> for Permutations<T> {
-    #[inline]
-    fn next(&mut self) -> Option<Vec<T>> {
-        match self.swaps.next() {
-            None => None,
-            Some((0,0)) => Some(self.v.clone()),
-            Some((a, b)) => {
-                let elt = self.v.clone();
-                self.v.swap(a, b);
-                Some(elt)
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.swaps.size_hint()
-    }
-}
-
-/// Extension methods for boxed slices.
-pub trait BoxedSliceExt<T> {
-    /// Convert `self` into a vector without clones or allocation.
-    fn into_vec(self) -> Vec<T>;
-}
-
-impl<T> BoxedSliceExt<T> for Box<[T]> {
-    #[experimental]
-    fn into_vec(mut self) -> Vec<T> {
-        unsafe {
-            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
-            mem::forget(self);
-            xs
-        }
-    }
-}
-
-/// Allocating extension methods for slices containing `Clone` elements.
-pub trait CloneSliceExt<T> for Sized? {
-    /// Copies `self` into a new `Vec`.
-    fn to_vec(&self) -> Vec<T>;
-
-    /// Partitions the vector into two vectors `(a, b)`, where all
-    /// elements of `a` satisfy `f` and all elements of `b` do not.
-    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool;
-
-    /// Creates an iterator that yields every possible permutation of the
-    /// vector in succession.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// for p in perms {
-    ///   println!("{}", p);
-    /// }
-    /// ```
-    ///
-    /// Iterating through permutations one by one.
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
-    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
-    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
-    /// ```
-    fn permutations(&self) -> Permutations<T>;
-
-    /// Copies as many elements from `src` as it can into `self` (the
-    /// shorter of `self.len()` and `src.len()`). Returns the number
-    /// of elements copied.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut dst = [0i, 0, 0];
-    /// let src = [1i, 2];
-    ///
-    /// assert!(dst.clone_from_slice(&src) == 2);
-    /// assert!(dst == [1, 2, 0]);
-    ///
-    /// let src2 = [3i, 4, 5, 6];
-    /// assert!(dst.clone_from_slice(&src2) == 3);
-    /// assert!(dst == [3i, 4, 5]);
-    /// ```
-    fn clone_from_slice(&mut self, &[T]) -> uint;
-}
-
-impl<T: Clone> CloneSliceExt<T> for [T] {
-    /// Returns a copy of `v`.
-    #[inline]
-    fn to_vec(&self) -> Vec<T> {
-        let mut vector = Vec::with_capacity(self.len());
-        vector.push_all(self);
-        vector
-    }
-
-
-    #[inline]
-    fn partitioned<F>(&self, mut f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
-        let mut lefts  = Vec::new();
-        let mut rights = Vec::new();
-
-        for elt in self.iter() {
-            if f(elt) {
-                lefts.push((*elt).clone());
-            } else {
-                rights.push((*elt).clone());
-            }
-        }
-
-        (lefts, rights)
-    }
-
-    /// Returns an iterator over all permutations of a vector.
-    fn permutations(&self) -> Permutations<T> {
-        Permutations{
-            swaps: ElementSwaps::new(self.len()),
-            v: self.to_vec(),
-        }
-    }
-
-    fn clone_from_slice(&mut self, src: &[T]) -> uint {
-        core_slice::CloneSliceExt::clone_from_slice(self, src)
-    }
-}
-
-fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
-    let len = v.len() as int;
-    let buf_v = v.as_mut_ptr();
-
-    // 1 <= i < len;
-    for i in range(1, len) {
-        // j satisfies: 0 <= j <= i;
-        let mut j = i;
-        unsafe {
-            // `i` is in bounds.
-            let read_ptr = buf_v.offset(i) as *const T;
-
-            // find where to insert, we need to do strict <,
-            // rather than <=, to maintain stability.
-
-            // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
-            while j > 0 &&
-                    compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
-                j -= 1;
-            }
-
-            // shift everything to the right, to make space to
-            // insert this value.
-
-            // j + 1 could be `len` (for the last `i`), but in
-            // that case, `i == j` so we don't copy. The
-            // `.offset(j)` is always in bounds.
-
-            if i != j {
-                let tmp = ptr::read(read_ptr);
-                ptr::copy_memory(buf_v.offset(j + 1),
-                                 &*buf_v.offset(j),
-                                 (i - j) as uint);
-                ptr::copy_nonoverlapping_memory(buf_v.offset(j),
-                                                &tmp as *const T,
-                                                1);
-                mem::forget(tmp);
-            }
-        }
-    }
-}
-
-fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
-    // warning: this wildly uses unsafe.
-    static BASE_INSERTION: uint = 32;
-    static LARGE_INSERTION: uint = 16;
-
-    // FIXME #12092: smaller insertion runs seems to make sorting
-    // vectors of large elements a little faster on some platforms,
-    // but hasn't been tested/tuned extensively
-    let insertion = if size_of::<T>() <= 16 {
-        BASE_INSERTION
-    } else {
-        LARGE_INSERTION
-    };
-
-    let len = v.len();
-
-    // short vectors get sorted in-place via insertion sort to avoid allocations
-    if len <= insertion {
-        insertion_sort(v, compare);
-        return;
-    }
-
-    // allocate some memory to use as scratch memory, we keep the
-    // length 0 so we can keep shallow copies of the contents of `v`
-    // without risking the dtors running on an object twice if
-    // `compare` panics.
-    let mut working_space = Vec::with_capacity(2 * len);
-    // these both are buffers of length `len`.
-    let mut buf_dat = working_space.as_mut_ptr();
-    let mut buf_tmp = unsafe {buf_dat.offset(len as int)};
-
-    // length `len`.
-    let buf_v = v.as_ptr();
-
-    // step 1. sort short runs with insertion sort. This takes the
-    // values from `v` and sorts them into `buf_dat`, leaving that
-    // with sorted runs of length INSERTION.
-
-    // We could hardcode the sorting comparisons here, and we could
-    // manipulate/step the pointers themselves, rather than repeatedly
-    // .offset-ing.
-    for start in range_step(0, len, insertion) {
-        // start <= i < len;
-        for i in range(start, cmp::min(start + insertion, len)) {
-            // j satisfies: start <= j <= i;
-            let mut j = i as int;
-            unsafe {
-                // `i` is in bounds.
-                let read_ptr = buf_v.offset(i as int);
-
-                // find where to insert, we need to do strict <,
-                // rather than <=, to maintain stability.
-
-                // start <= j - 1 < len, so .offset(j - 1) is in
-                // bounds.
-                while j > start as int &&
-                        compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
-                    j -= 1;
-                }
-
-                // shift everything to the right, to make space to
-                // insert this value.
-
-                // j + 1 could be `len` (for the last `i`), but in
-                // that case, `i == j` so we don't copy. The
-                // `.offset(j)` is always in bounds.
-                ptr::copy_memory(buf_dat.offset(j + 1),
-                                 &*buf_dat.offset(j),
-                                 i - j as uint);
-                ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
-            }
-        }
-    }
-
-    // step 2. merge the sorted runs.
-    let mut width = insertion;
-    while width < len {
-        // merge the sorted runs of length `width` in `buf_dat` two at
-        // a time, placing the result in `buf_tmp`.
-
-        // 0 <= start <= len.
-        for start in range_step(0, len, 2 * width) {
-            // manipulate pointers directly for speed (rather than
-            // using a `for` loop with `range` and `.offset` inside
-            // that loop).
-            unsafe {
-                // the end of the first run & start of the
-                // second. Offset of `len` is defined, since this is
-                // precisely one byte past the end of the object.
-                let right_start = buf_dat.offset(cmp::min(start + width, len) as int);
-                // end of the second. Similar reasoning to the above re safety.
-                let right_end_idx = cmp::min(start + 2 * width, len);
-                let right_end = buf_dat.offset(right_end_idx as int);
-
-                // the pointers to the elements under consideration
-                // from the two runs.
-
-                // both of these are in bounds.
-                let mut left = buf_dat.offset(start as int);
-                let mut right = right_start;
-
-                // where we're putting the results, it is a run of
-                // length `2*width`, so we step it once for each step
-                // of either `left` or `right`.  `buf_tmp` has length
-                // `len`, so these are in bounds.
-                let mut out = buf_tmp.offset(start as int);
-                let out_end = buf_tmp.offset(right_end_idx as int);
-
-                while out < out_end {
-                    // Either the left or the right run are exhausted,
-                    // so just copy the remainder from the other run
-                    // and move on; this gives a huge speed-up (order
-                    // of 25%) for mostly sorted vectors (the best
-                    // case).
-                    if left == right_start {
-                        // the number remaining in this run.
-                        let elems = (right_end as uint - right as uint) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*right, elems);
-                        break;
-                    } else if right == right_end {
-                        let elems = (right_start as uint - left as uint) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*left, elems);
-                        break;
-                    }
-
-                    // check which side is smaller, and that's the
-                    // next element for the new run.
-
-                    // `left < right_start` and `right < right_end`,
-                    // so these are valid.
-                    let to_copy = if compare(&*left, &*right) == Greater {
-                        step(&mut right)
-                    } else {
-                        step(&mut left)
-                    };
-                    ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
-                    step(&mut out);
-                }
-            }
-        }
-
-        mem::swap(&mut buf_dat, &mut buf_tmp);
-
-        width *= 2;
-    }
-
-    // write the result to `v` in one go, so that there are never two copies
-    // of the same object in `v`.
-    unsafe {
-        ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
-    }
-
-    // increment the pointer, returning the old pointer.
-    #[inline(always)]
-    unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
-        let old = *ptr;
-        *ptr = ptr.offset(1);
-        old
-    }
-}
-
-/// Allocating extension methods for slices on Ord values.
-#[experimental = "likely to merge with other traits"]
-pub trait OrdSliceExt<T> for Sized? {
-    /// Sorts the slice, in place.
-    ///
-    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let mut v = [-5i, 4, 1, -3, 2];
-    ///
-    /// v.sort();
-    /// assert!(v == [-5i, -3, 1, 2, 4]);
-    /// ```
-    #[experimental]
-    fn sort(&mut self);
-
-    /// Binary search a sorted slice for a given element.
-    ///
-    /// If the value is found then `Found` is returned, containing the
-    /// index of the matching element; if the value is not found then
-    /// `NotFound` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Example
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1,4]`.
-    ///
-    /// ```rust
-    /// use std::slice::BinarySearchResult::{Found, NotFound};
-    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    /// let s = s.as_slice();
-    ///
-    /// assert_eq!(s.binary_search_elem(&13),  Found(9));
-    /// assert_eq!(s.binary_search_elem(&4),   NotFound(7));
-    /// assert_eq!(s.binary_search_elem(&100), NotFound(13));
-    /// let r = s.binary_search_elem(&1);
-    /// assert!(match r { Found(1...4) => true, _ => false, });
-    /// ```
-    #[unstable = "name likely to change"]
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
-
-    /// Mutates the slice to the next lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// last-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [0i, 1, 2];
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [1i, 0, 2];
-    /// assert!(v == b);
-    /// ```
-    #[experimental]
-    fn next_permutation(&mut self) -> bool;
-
-    /// Mutates the slice to the previous lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// first-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [1i, 0, 2];
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 1, 2];
-    /// assert!(v == b);
-    /// ```
-    #[experimental]
-    fn prev_permutation(&mut self) -> bool;
-}
-
-impl<T: Ord> OrdSliceExt<T> for [T] {
-    #[inline]
-    fn sort(&mut self) {
-        self.sort_by(|a, b| a.cmp(b))
-    }
-
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
-        core_slice::OrdSliceExt::binary_search_elem(self, x)
-    }
-
-    fn next_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::next_permutation(self)
-    }
-
-    fn prev_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::prev_permutation(self)
-    }
-}
+////////////////////////////////////////////////////////////////////////////////
+// Basic slice extension methods
+////////////////////////////////////////////////////////////////////////////////
 
 /// Allocating extension methods for slices.
-#[experimental = "likely to merge with other traits"]
+#[unstable = "needs associated types, may merge with other traits"]
 pub trait SliceExt<T> for Sized? {
     /// Sorts the slice, in place, using `compare` to compare
     /// elements.
@@ -709,6 +134,7 @@ pub trait SliceExt<T> for Sized? {
     /// v.sort_by(|a, b| b.cmp(a));
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
+    #[stable]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering;
 
     /// Consumes `src` and moves as many elements as it can into `self`
@@ -732,6 +158,7 @@ pub trait SliceExt<T> for Sized? {
     /// assert_eq!(num_moved, 3);
     /// assert!(a == [6i, 7, 8, 4, 5]);
     /// ```
+    #[experimental = "uncertain about this API approach"]
     fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint;
 
     /// Returns a subslice spanning the interval [`start`, `end`).
@@ -740,7 +167,7 @@ pub trait SliceExt<T> for Sized? {
     /// original slice (i.e. when `end > self.len()`) or when `start > end`.
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
-    #[unstable = "waiting on final error conventions/slicing syntax"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice(&self, start: uint, end: uint) -> &[T];
 
     /// Returns a subslice from `start` to the end of the slice.
@@ -748,7 +175,7 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `start` is strictly greater than the length of the original slice.
     ///
     /// Slicing from `self.len()` yields an empty slice.
-    #[unstable = "waiting on final error conventions/slicing syntax"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_from(&self, start: uint) -> &[T];
 
     /// Returns a subslice from the start of the slice to `end`.
@@ -756,7 +183,7 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `end` is strictly greater than the length of the original slice.
     ///
     /// Slicing to `0` yields an empty slice.
-    #[unstable = "waiting on final error conventions/slicing syntax"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_to(&self, end: uint) -> &[T];
 
     /// Divides one slice into two at an index.
@@ -766,32 +193,32 @@ pub trait SliceExt<T> for Sized? {
     /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
     /// Panics if `mid > len`.
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn split_at(&self, mid: uint) -> (&[T], &[T]);
 
     /// Returns an iterator over the slice
-    #[unstable = "iterator type may change"]
+    #[stable]
     fn iter(&self) -> Iter<T>;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`.  The matched element is not contained in the subslices.
-    #[unstable = "iterator type may change, waiting on unboxed closures"]
-    fn split<F>(&self, pred: F) -> Splits<T, F>
+    #[stable]
+    fn split<F>(&self, pred: F) -> Split<T, F>
                 where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
-    #[unstable = "iterator type may change"]
-    fn splitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    #[stable]
+    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F>
                  where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
-    #[unstable = "iterator type may change"]
-    fn rsplitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    #[stable]
+    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F>
                   where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over all contiguous windows of length
@@ -813,7 +240,7 @@ pub trait SliceExt<T> for Sized? {
     ///     println!("{}", win);
     /// }
     /// ```
-    #[unstable = "iterator type may change"]
+    #[stable]
     fn windows(&self, size: uint) -> Windows<T>;
 
     /// Returns an iterator over `size` elements of the slice at a
@@ -836,34 +263,44 @@ pub trait SliceExt<T> for Sized? {
     ///     println!("{}", win);
     /// }
     /// ```
-    #[unstable = "iterator type may change"]
+    #[stable]
     fn chunks(&self, size: uint) -> Chunks<T>;
 
     /// Returns the element of a slice at the given index, or `None` if the
     /// index is out of bounds.
-    #[unstable = "waiting on final collection conventions"]
+    #[stable]
     fn get(&self, index: uint) -> Option<&T>;
 
     /// Returns the first element of a slice, or `None` if it is empty.
-    #[unstable = "name may change"]
-    fn head(&self) -> Option<&T>;
+    #[stable]
+    fn first(&self) -> Option<&T>;
+
+    /// Deprecated: renamed to `first`.
+    #[deprecated = "renamed to `first`"]
+    fn head(&self) -> Option<&T> { self.first() }
 
     /// Returns all but the first element of a slice.
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed"]
     fn tail(&self) -> &[T];
 
     /// Returns all but the last element of a slice.
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed"]
     fn init(&self) -> &[T];
 
     /// Returns the last element of a slice, or `None` if it is empty.
-    #[unstable = "name may change"]
+    #[stable]
     fn last(&self) -> Option<&T>;
 
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
-    #[unstable]
-    unsafe fn unsafe_get(&self, index: uint) -> &T;
+    #[stable]
+    unsafe fn get_unchecked(&self, index: uint) -> &T;
+
+    /// Deprecated: renamed to `get_unchecked`.
+    #[deprecated = "renamed to get_unchecked"]
+    unsafe fn unsafe_get(&self, index: uint) -> &T {
+        self.get_unchecked(index)
+    }
 
     /// Returns an unsafe pointer to the slice's buffer
     ///
@@ -872,7 +309,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
-    #[unstable]
+    #[stable]
     fn as_ptr(&self) -> *const T;
 
     /// Binary search a sorted slice with a comparator function.
@@ -882,9 +319,9 @@ pub trait SliceExt<T> for Sized? {
     /// order code that indicates whether its argument is `Less`,
     /// `Equal` or `Greater` the desired target.
     ///
-    /// If a matching value is found then returns `Found`, containing
+    /// If a matching value is found then returns `Ok`, containing
     /// the index for the matched element; if no match is found then
-    /// `NotFound` is returned, containing the index where a matching
+    /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
     /// # Example
@@ -894,23 +331,22 @@ pub trait SliceExt<T> for Sized? {
     /// found; the fourth could match any position in `[1,4]`.
     ///
     /// ```rust
-    /// use std::slice::BinarySearchResult::{Found, NotFound};
     /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
     /// let s = s.as_slice();
     ///
     /// let seek = 13;
-    /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), Found(9));
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
     /// let seek = 4;
-    /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), NotFound(7));
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
     /// let seek = 100;
-    /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), NotFound(13));
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
     /// let seek = 1;
-    /// let r = s.binary_search(|probe| probe.cmp(&seek));
-    /// assert!(match r { Found(1...4) => true, _ => false, });
+    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
     /// ```
-    #[unstable = "waiting on unboxed closures"]
-    fn binary_search<F>(&self, f: F) -> BinarySearchResult
-                        where F: FnMut(&T) -> Ordering;
+    #[stable]
+    fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
+        F: FnMut(&T) -> Ordering;
 
     /// Return the number of elements in the slice
     ///
@@ -920,7 +356,7 @@ pub trait SliceExt<T> for Sized? {
     /// let a = [1i, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
-    #[experimental = "not triaged yet"]
+    #[stable]
     fn len(&self) -> uint;
 
     /// Returns true if the slice has a length of 0
@@ -932,15 +368,16 @@ pub trait SliceExt<T> for Sized? {
     /// assert!(!a.is_empty());
     /// ```
     #[inline]
-    #[experimental = "not triaged yet"]
+    #[stable]
     fn is_empty(&self) -> bool { self.len() == 0 }
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn get_mut(&mut self, index: uint) -> Option<&mut T>;
 
     /// Work with `self` as a mut slice.
     /// Primarily intended for getting a &mut [T] from a [T, ..N].
+    #[stable]
     fn as_mut_slice(&mut self) -> &mut [T];
 
     /// Returns a mutable subslice spanning the interval [`start`, `end`).
@@ -949,7 +386,7 @@ pub trait SliceExt<T> for Sized? {
     /// original slice (i.e. when `end > self.len()`) or when `start > end`.
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
-    #[unstable = "waiting on final error conventions"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T];
 
     /// Returns a mutable subslice from `start` to the end of the slice.
@@ -957,7 +394,7 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `start` is strictly greater than the length of the original slice.
     ///
     /// Slicing from `self.len()` yields an empty slice.
-    #[unstable = "waiting on final error conventions"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_from_mut(&mut self, start: uint) -> &mut [T];
 
     /// Returns a mutable subslice from the start of the slice to `end`.
@@ -965,48 +402,54 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `end` is strictly greater than the length of the original slice.
     ///
     /// Slicing to `0` yields an empty slice.
-    #[unstable = "waiting on final error conventions"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_to_mut(&mut self, end: uint) -> &mut [T];
 
     /// Returns an iterator that allows modifying each value
-    #[unstable = "waiting on iterator type name conventions"]
+    #[stable]
     fn iter_mut(&mut self) -> IterMut<T>;
 
     /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
-    #[unstable = "name may change"]
-    fn head_mut(&mut self) -> Option<&mut T>;
+    #[stable]
+    fn first_mut(&mut self) -> Option<&mut T>;
+
+    /// Depreated: renamed to `first_mut`.
+    #[deprecated = "renamed to first_mut"]
+    fn head_mut(&mut self) -> Option<&mut T> {
+        self.first_mut()
+    }
 
     /// Returns all but the first element of a mutable slice
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed or removed"]
     fn tail_mut(&mut self) -> &mut [T];
 
     /// Returns all but the last element of a mutable slice
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed or removed"]
     fn init_mut(&mut self) -> &mut [T];
 
     /// Returns a mutable pointer to the last item in the slice.
-    #[unstable = "name may change"]
+    #[stable]
     fn last_mut(&mut self) -> Option<&mut T>;
 
     /// Returns an iterator over mutable subslices separated by elements that
     /// match `pred`.  The matched element is not contained in the subslices.
-    #[unstable = "waiting on unboxed closures, iterator type name conventions"]
-    fn split_mut<F>(&mut self, pred: F) -> MutSplits<T, F>
+    #[stable]
+    fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
                     where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
-    #[unstable = "waiting on unboxed closures, iterator type name conventions"]
-    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    #[stable]
+    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F>
                      where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
-    #[unstable = "waiting on unboxed closures, iterator type name conventions"]
-    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    #[stable]
+    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<T, F>
                       where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
@@ -1017,18 +460,20 @@ pub trait SliceExt<T> for Sized? {
     /// # Panics
     ///
     /// Panics if `chunk_size` is 0.
-    #[unstable = "waiting on iterator type name conventions"]
-    fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks<T>;
+    #[stable]
+    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T>;
 
     /// Swaps two elements in a slice.
     ///
-    /// Panics if `a` or `b` are out of bounds.
-    ///
     /// # Arguments
     ///
     /// * a - The index of the first element
     /// * b - The index of the second element
     ///
+    /// # Panics
+    ///
+    /// Panics if `a` or `b` are out of bounds.
+    ///
     /// # Example
     ///
     /// ```rust
@@ -1036,7 +481,7 @@ pub trait SliceExt<T> for Sized? {
     /// v.swap(1, 3);
     /// assert!(v == ["a", "d", "c", "b"]);
     /// ```
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn swap(&mut self, a: uint, b: uint);
 
     /// Divides one `&mut` into two at an index.
@@ -1045,6 +490,8 @@ pub trait SliceExt<T> for Sized? {
     /// the index `mid` itself) and the second will contain all
     /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
+    /// # Panics
+    ///
     /// Panics if `mid > len`.
     ///
     /// # Example
@@ -1071,7 +518,7 @@ pub trait SliceExt<T> for Sized? {
     ///     assert!(right == []);
     /// }
     /// ```
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]);
 
     /// Reverse the order of elements in a slice, in place.
@@ -1083,12 +530,18 @@ pub trait SliceExt<T> for Sized? {
     /// v.reverse();
     /// assert!(v == [3i, 2, 1]);
     /// ```
-    #[experimental = "may be moved to iterators instead"]
+    #[stable]
     fn reverse(&mut self);
 
     /// Returns an unsafe mutable pointer to the element in index
-    #[experimental = "waiting on unsafe conventions"]
-    unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T;
+    #[stable]
+    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T;
+
+    /// Deprecated: renamed to `get_unchecked_mut`.
+    #[deprecated = "renamed to get_unchecked_mut"]
+    unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T {
+        self.get_unchecked_mut(index)
+    }
 
     /// Return an unsafe mutable pointer to the slice's buffer.
     ///
@@ -1098,10 +551,11 @@ pub trait SliceExt<T> for Sized? {
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
     #[inline]
-    #[unstable]
+    #[stable]
     fn as_mut_ptr(&mut self) -> *mut T;
 }
 
+#[unstable = "trait is unstable"]
 impl<T> SliceExt<T> for [T] {
     #[inline]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering {
@@ -1142,19 +596,19 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split<F>(&self, pred: F) -> Splits<T, F>
+    fn split<F>(&self, pred: F) -> Split<T, F>
                 where F: FnMut(&T) -> bool {
         core_slice::SliceExt::split(self, pred)
     }
 
     #[inline]
-    fn splitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F>
                  where F: FnMut(&T) -> bool {
         core_slice::SliceExt::splitn(self, n, pred)
     }
 
     #[inline]
-    fn rsplitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F>
                   where F: FnMut(&T) -> bool {
         core_slice::SliceExt::rsplitn(self, n, pred)
     }
@@ -1175,8 +629,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head<'a>(&'a self) -> Option<&'a T> {
-        core_slice::SliceExt::head(self)
+    fn first<'a>(&'a self) -> Option<&'a T> {
+        core_slice::SliceExt::first(self)
     }
 
     #[inline]
@@ -1195,8 +649,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T {
-        core_slice::SliceExt::unsafe_get(self, index)
+    unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T {
+        core_slice::SliceExt::get_unchecked(self, index)
     }
 
     #[inline]
@@ -1205,9 +659,9 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn binary_search<F>(&self, f: F) -> BinarySearchResult
+    fn binary_search_by<F>(&self, f: F) -> Result<uint, uint>
                         where F: FnMut(&T) -> Ordering {
-        core_slice::SliceExt::binary_search(self, f)
+        core_slice::SliceExt::binary_search_by(self, f)
     }
 
     #[inline]
@@ -1251,8 +705,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head_mut<'a>(&'a mut self) -> Option<&'a mut T> {
-        core_slice::SliceExt::head_mut(self)
+    fn first_mut<'a>(&'a mut self) -> Option<&'a mut T> {
+        core_slice::SliceExt::first_mut(self)
     }
 
     #[inline]
@@ -1271,25 +725,25 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split_mut<F>(&mut self, pred: F) -> MutSplits<T, F>
+    fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
                     where F: FnMut(&T) -> bool {
         core_slice::SliceExt::split_mut(self, pred)
     }
 
     #[inline]
-    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F>
                      where F: FnMut(&T) -> bool {
         core_slice::SliceExt::splitn_mut(self, n, pred)
     }
 
     #[inline]
-    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<T, F>
                       where F: FnMut(&T) -> bool {
         core_slice::SliceExt::rsplitn_mut(self, n, pred)
     }
 
     #[inline]
-    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T> {
+    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T> {
         core_slice::SliceExt::chunks_mut(self, chunk_size)
     }
 
@@ -1309,8 +763,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
-        core_slice::SliceExt::unsafe_mut(self, index)
+    unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
+        core_slice::SliceExt::get_unchecked_mut(self, index)
     }
 
     #[inline]
@@ -1319,6 +773,297 @@ impl<T> SliceExt<T> for [T] {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Extension traits for slices over specifc kinds of data
+////////////////////////////////////////////////////////////////////////////////
+
+/// Extension methods for boxed slices.
+#[experimental = "likely to merge into SliceExt if it survives"]
+pub trait BoxedSliceExt<T> {
+    /// Convert `self` into a vector without clones or allocation.
+    #[experimental]
+    fn into_vec(self) -> Vec<T>;
+}
+
+#[experimental = "trait is experimental"]
+impl<T> BoxedSliceExt<T> for Box<[T]> {
+    fn into_vec(mut self) -> Vec<T> {
+        unsafe {
+            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
+            mem::forget(self);
+            xs
+        }
+    }
+}
+
+/// Allocating extension methods for slices containing `Clone` elements.
+#[unstable = "likely to be merged into SliceExt"]
+pub trait CloneSliceExt<T> for Sized? {
+    /// Copies `self` into a new `Vec`.
+    #[stable]
+    fn to_vec(&self) -> Vec<T>;
+
+    /// Deprecated: use `iter().cloned().partition(f)` instead.
+    #[deprecated = "use iter().cloned().partition(f) instead"]
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool;
+
+    /// Creates an iterator that yields every possible permutation of the
+    /// vector in succession.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let v = [1i, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// for p in perms {
+    ///   println!("{}", p);
+    /// }
+    /// ```
+    ///
+    /// Iterating through permutations one by one.
+    ///
+    /// ```rust
+    /// let v = [1i, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
+    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
+    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
+    /// ```
+    #[stable]
+    fn permutations(&self) -> Permutations<T>;
+
+    /// Copies as many elements from `src` as it can into `self` (the
+    /// shorter of `self.len()` and `src.len()`). Returns the number
+    /// of elements copied.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut dst = [0i, 0, 0];
+    /// let src = [1i, 2];
+    ///
+    /// assert!(dst.clone_from_slice(&src) == 2);
+    /// assert!(dst == [1, 2, 0]);
+    ///
+    /// let src2 = [3i, 4, 5, 6];
+    /// assert!(dst.clone_from_slice(&src2) == 3);
+    /// assert!(dst == [3i, 4, 5]);
+    /// ```
+    #[experimental]
+    fn clone_from_slice(&mut self, &[T]) -> uint;
+}
+
+#[unstable = "trait is unstable"]
+impl<T: Clone> CloneSliceExt<T> for [T] {
+    /// Returns a copy of `v`.
+    #[inline]
+    fn to_vec(&self) -> Vec<T> {
+        let mut vector = Vec::with_capacity(self.len());
+        vector.push_all(self);
+        vector
+    }
+
+
+    #[inline]
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
+        self.iter().cloned().partition(f)
+    }
+
+    /// Returns an iterator over all permutations of a vector.
+    fn permutations(&self) -> Permutations<T> {
+        Permutations{
+            swaps: ElementSwaps::new(self.len()),
+            v: self.to_vec(),
+        }
+    }
+
+    fn clone_from_slice(&mut self, src: &[T]) -> uint {
+        core_slice::CloneSliceExt::clone_from_slice(self, src)
+    }
+}
+
+/// Allocating extension methods for slices on Ord values.
+#[unstable = "likely to merge with SliceExt"]
+pub trait OrdSliceExt<T> for Sized? {
+    /// Sorts the slice, in place.
+    ///
+    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut v = [-5i, 4, 1, -3, 2];
+    ///
+    /// v.sort();
+    /// assert!(v == [-5i, -3, 1, 2, 4]);
+    /// ```
+    #[stable]
+    fn sort(&mut self);
+
+    /// Binary search a sorted slice for a given element.
+    ///
+    /// If the value is found then `Ok` is returned, containing the
+    /// index of the matching element; if the value is not found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Example
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1,4]`.
+    ///
+    /// ```rust
+    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    /// let s = s.as_slice();
+    ///
+    /// assert_eq!(s.binary_search(&13),  Ok(9));
+    /// assert_eq!(s.binary_search(&4),   Err(7));
+    /// assert_eq!(s.binary_search(&100), Err(13));
+    /// let r = s.binary_search(&1);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable]
+    fn binary_search(&self, x: &T) -> Result<uint, uint>;
+
+    /// Deprecated: use `binary_search` instead.
+    #[deprecated = "use binary_search instead"]
+    fn binary_search_elem(&self, x: &T) -> Result<uint, uint> {
+        self.binary_search(x)
+    }
+
+    /// Mutates the slice to the next lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// last-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [0i, 1, 2];
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [1i, 0, 2];
+    /// assert!(v == b);
+    /// ```
+    #[stable]
+    fn next_permutation(&mut self) -> bool;
+
+    /// Mutates the slice to the previous lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// first-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [1i, 0, 2];
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 1, 2];
+    /// assert!(v == b);
+    /// ```
+    #[stable]
+    fn prev_permutation(&mut self) -> bool;
+}
+
+#[unstable = "trait is unstable"]
+impl<T: Ord> OrdSliceExt<T> for [T] {
+    #[inline]
+    fn sort(&mut self) {
+        self.sort_by(|a, b| a.cmp(b))
+    }
+
+    fn binary_search(&self, x: &T) -> Result<uint, uint> {
+        core_slice::OrdSliceExt::binary_search(self, x)
+    }
+
+    fn next_permutation(&mut self) -> bool {
+        core_slice::OrdSliceExt::next_permutation(self)
+    }
+
+    fn prev_permutation(&mut self) -> bool {
+        core_slice::OrdSliceExt::prev_permutation(self)
+    }
+}
+
+#[allow(missing_docs)]
+pub trait VectorVector<T> for Sized? {
+    // FIXME #5898: calling these .concat and .connect conflicts with
+    // StrVector::con{cat,nect}, since they have generic contents.
+    /// Flattens a vector of vectors of `T` into a single `Vec<T>`.
+    fn concat_vec(&self) -> Vec<T>;
+
+    /// Concatenate a vector of vectors, placing a given separator between each.
+    fn connect_vec(&self, sep: &T) -> Vec<T>;
+}
+
+impl<'a, T: Clone, V: AsSlice<T>> VectorVector<T> for [V] {
+    fn concat_vec(&self) -> Vec<T> {
+        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
+        let mut result = Vec::with_capacity(size);
+        for v in self.iter() {
+            result.push_all(v.as_slice())
+        }
+        result
+    }
+
+    fn connect_vec(&self, sep: &T) -> Vec<T> {
+        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
+        let mut result = Vec::with_capacity(size + self.len());
+        let mut first = true;
+        for v in self.iter() {
+            if first { first = false } else { result.push(sep.clone()) }
+            result.push_all(v.as_slice())
+        }
+        result
+    }
+}
+
+/// An iterator that yields the element swaps needed to produce
+/// a sequence of all possible permutations for an indexed sequence of
+/// elements. Each permutation is only a single swap apart.
+///
+/// The Steinhaus-Johnson-Trotter algorithm is used.
+///
+/// Generates even and odd permutations alternately.
+///
+/// The last generated swap is always (0, 1), and it returns the
+/// sequence to its initial order.
+#[experimental]
+pub struct ElementSwaps {
+    sdir: Vec<SizeDirection>,
+    /// If `true`, emit the last swap that returns the sequence to initial
+    /// state.
+    emit_reset: bool,
+    swaps_made : uint,
+}
+
+impl ElementSwaps {
+    /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
+    #[experimental]
+    pub fn new(length: uint) -> ElementSwaps {
+        // Initialize `sdir` with a direction that position should move in
+        // (all negative at the beginning) and the `size` of the
+        // element (equal to the original index).
+        ElementSwaps{
+            emit_reset: true,
+            sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
+            swaps_made: 0
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Standard trait implementations for slices
+////////////////////////////////////////////////////////////////////////////////
+
 #[unstable = "trait is unstable"]
 impl<T> BorrowFrom<Vec<T>> for [T] {
     fn borrow_from(owned: &Vec<T>) -> &[T] { owned[] }
@@ -1334,7 +1079,316 @@ impl<T: Clone> ToOwned<Vec<T>> for [T] {
     fn to_owned(&self) -> Vec<T> { self.to_vec() }
 }
 
-/// Unsafe operations
+////////////////////////////////////////////////////////////////////////////////
+// Iterators
+////////////////////////////////////////////////////////////////////////////////
+
+#[deriving(Copy)]
+enum Direction { Pos, Neg }
+
+/// An `Index` and `Direction` together.
+#[deriving(Copy)]
+struct SizeDirection {
+    size: uint,
+    dir: Direction,
+}
+
+impl Iterator<(uint, uint)> for ElementSwaps {
+    #[inline]
+    fn next(&mut self) -> Option<(uint, uint)> {
+        fn new_pos(i: uint, s: Direction) -> uint {
+            i + match s { Pos => 1, Neg => -1 }
+        }
+
+        // Find the index of the largest mobile element:
+        // The direction should point into the vector, and the
+        // swap should be with a smaller `size` element.
+        let max = self.sdir.iter().map(|&x| x).enumerate()
+                           .filter(|&(i, sd)|
+                                new_pos(i, sd.dir) < self.sdir.len() &&
+                                self.sdir[new_pos(i, sd.dir)].size < sd.size)
+                           .max_by(|&(_, sd)| sd.size);
+        match max {
+            Some((i, sd)) => {
+                let j = new_pos(i, sd.dir);
+                self.sdir.swap(i, j);
+
+                // Swap the direction of each larger SizeDirection
+                for x in self.sdir.iter_mut() {
+                    if x.size > sd.size {
+                        x.dir = match x.dir { Pos => Neg, Neg => Pos };
+                    }
+                }
+                self.swaps_made += 1;
+                Some((i, j))
+            },
+            None => if self.emit_reset {
+                self.emit_reset = false;
+                if self.sdir.len() > 1 {
+                    // The last swap
+                    self.swaps_made += 1;
+                    Some((0, 1))
+                } else {
+                    // Vector is of the form [] or [x], and the only permutation is itself
+                    self.swaps_made += 1;
+                    Some((0,0))
+                }
+            } else { None }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        // For a vector of size n, there are exactly n! permutations.
+        let n = range(2, self.sdir.len() + 1).product();
+        (n - self.swaps_made, Some(n - self.swaps_made))
+    }
+}
+
+/// An iterator that uses `ElementSwaps` to iterate through
+/// all possible permutations of a vector.
+///
+/// The first iteration yields a clone of the vector as it is,
+/// then each successive element is the vector with one
+/// swap applied.
+///
+/// Generates even and odd permutations alternately.
+#[stable]
+pub struct Permutations<T> {
+    swaps: ElementSwaps,
+    v: Vec<T>,
+}
+
+#[unstable = "trait is unstable"]
+impl<T: Clone> Iterator<Vec<T>> for Permutations<T> {
+    #[inline]
+    fn next(&mut self) -> Option<Vec<T>> {
+        match self.swaps.next() {
+            None => None,
+            Some((0,0)) => Some(self.v.clone()),
+            Some((a, b)) => {
+                let elt = self.v.clone();
+                self.v.swap(a, b);
+                Some(elt)
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        self.swaps.size_hint()
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sorting
+////////////////////////////////////////////////////////////////////////////////
+
+fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
+    let len = v.len() as int;
+    let buf_v = v.as_mut_ptr();
+
+    // 1 <= i < len;
+    for i in range(1, len) {
+        // j satisfies: 0 <= j <= i;
+        let mut j = i;
+        unsafe {
+            // `i` is in bounds.
+            let read_ptr = buf_v.offset(i) as *const T;
+
+            // find where to insert, we need to do strict <,
+            // rather than <=, to maintain stability.
+
+            // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
+            while j > 0 &&
+                    compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
+                j -= 1;
+            }
+
+            // shift everything to the right, to make space to
+            // insert this value.
+
+            // j + 1 could be `len` (for the last `i`), but in
+            // that case, `i == j` so we don't copy. The
+            // `.offset(j)` is always in bounds.
+
+            if i != j {
+                let tmp = ptr::read(read_ptr);
+                ptr::copy_memory(buf_v.offset(j + 1),
+                                 &*buf_v.offset(j),
+                                 (i - j) as uint);
+                ptr::copy_nonoverlapping_memory(buf_v.offset(j),
+                                                &tmp as *const T,
+                                                1);
+                mem::forget(tmp);
+            }
+        }
+    }
+}
+
+fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
+    // warning: this wildly uses unsafe.
+    static BASE_INSERTION: uint = 32;
+    static LARGE_INSERTION: uint = 16;
+
+    // FIXME #12092: smaller insertion runs seems to make sorting
+    // vectors of large elements a little faster on some platforms,
+    // but hasn't been tested/tuned extensively
+    let insertion = if size_of::<T>() <= 16 {
+        BASE_INSERTION
+    } else {
+        LARGE_INSERTION
+    };
+
+    let len = v.len();
+
+    // short vectors get sorted in-place via insertion sort to avoid allocations
+    if len <= insertion {
+        insertion_sort(v, compare);
+        return;
+    }
+
+    // allocate some memory to use as scratch memory, we keep the
+    // length 0 so we can keep shallow copies of the contents of `v`
+    // without risking the dtors running on an object twice if
+    // `compare` panics.
+    let mut working_space = Vec::with_capacity(2 * len);
+    // these both are buffers of length `len`.
+    let mut buf_dat = working_space.as_mut_ptr();
+    let mut buf_tmp = unsafe {buf_dat.offset(len as int)};
+
+    // length `len`.
+    let buf_v = v.as_ptr();
+
+    // step 1. sort short runs with insertion sort. This takes the
+    // values from `v` and sorts them into `buf_dat`, leaving that
+    // with sorted runs of length INSERTION.
+
+    // We could hardcode the sorting comparisons here, and we could
+    // manipulate/step the pointers themselves, rather than repeatedly
+    // .offset-ing.
+    for start in range_step(0, len, insertion) {
+        // start <= i < len;
+        for i in range(start, cmp::min(start + insertion, len)) {
+            // j satisfies: start <= j <= i;
+            let mut j = i as int;
+            unsafe {
+                // `i` is in bounds.
+                let read_ptr = buf_v.offset(i as int);
+
+                // find where to insert, we need to do strict <,
+                // rather than <=, to maintain stability.
+
+                // start <= j - 1 < len, so .offset(j - 1) is in
+                // bounds.
+                while j > start as int &&
+                        compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
+                    j -= 1;
+                }
+
+                // shift everything to the right, to make space to
+                // insert this value.
+
+                // j + 1 could be `len` (for the last `i`), but in
+                // that case, `i == j` so we don't copy. The
+                // `.offset(j)` is always in bounds.
+                ptr::copy_memory(buf_dat.offset(j + 1),
+                                 &*buf_dat.offset(j),
+                                 i - j as uint);
+                ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
+            }
+        }
+    }
+
+    // step 2. merge the sorted runs.
+    let mut width = insertion;
+    while width < len {
+        // merge the sorted runs of length `width` in `buf_dat` two at
+        // a time, placing the result in `buf_tmp`.
+
+        // 0 <= start <= len.
+        for start in range_step(0, len, 2 * width) {
+            // manipulate pointers directly for speed (rather than
+            // using a `for` loop with `range` and `.offset` inside
+            // that loop).
+            unsafe {
+                // the end of the first run & start of the
+                // second. Offset of `len` is defined, since this is
+                // precisely one byte past the end of the object.
+                let right_start = buf_dat.offset(cmp::min(start + width, len) as int);
+                // end of the second. Similar reasoning to the above re safety.
+                let right_end_idx = cmp::min(start + 2 * width, len);
+                let right_end = buf_dat.offset(right_end_idx as int);
+
+                // the pointers to the elements under consideration
+                // from the two runs.
+
+                // both of these are in bounds.
+                let mut left = buf_dat.offset(start as int);
+                let mut right = right_start;
+
+                // where we're putting the results, it is a run of
+                // length `2*width`, so we step it once for each step
+                // of either `left` or `right`.  `buf_tmp` has length
+                // `len`, so these are in bounds.
+                let mut out = buf_tmp.offset(start as int);
+                let out_end = buf_tmp.offset(right_end_idx as int);
+
+                while out < out_end {
+                    // Either the left or the right run are exhausted,
+                    // so just copy the remainder from the other run
+                    // and move on; this gives a huge speed-up (order
+                    // of 25%) for mostly sorted vectors (the best
+                    // case).
+                    if left == right_start {
+                        // the number remaining in this run.
+                        let elems = (right_end as uint - right as uint) / mem::size_of::<T>();
+                        ptr::copy_nonoverlapping_memory(out, &*right, elems);
+                        break;
+                    } else if right == right_end {
+                        let elems = (right_start as uint - left as uint) / mem::size_of::<T>();
+                        ptr::copy_nonoverlapping_memory(out, &*left, elems);
+                        break;
+                    }
+
+                    // check which side is smaller, and that's the
+                    // next element for the new run.
+
+                    // `left < right_start` and `right < right_end`,
+                    // so these are valid.
+                    let to_copy = if compare(&*left, &*right) == Greater {
+                        step(&mut right)
+                    } else {
+                        step(&mut left)
+                    };
+                    ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
+                    step(&mut out);
+                }
+            }
+        }
+
+        mem::swap(&mut buf_dat, &mut buf_tmp);
+
+        width *= 2;
+    }
+
+    // write the result to `v` in one go, so that there are never two copies
+    // of the same object in `v`.
+    unsafe {
+        ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
+    }
+
+    // increment the pointer, returning the old pointer.
+    #[inline(always)]
+    unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
+        let old = *ptr;
+        *ptr = ptr.offset(1);
+        old
+    }
+}
+
+/// Deprecated, unsafe operations
+#[deprecated]
 pub mod raw {
     pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
     pub use core::slice::raw::{shift_ptr, pop_ptr};
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index f356a0867d2..38d8977c0aa 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -68,23 +68,23 @@ pub trait SliceExt<T> for Sized? {
     fn slice_to<'a>(&'a self, end: uint) -> &'a [T];
     fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]);
     fn iter<'a>(&'a self) -> Iter<'a, T>;
-    fn split<'a, P>(&'a self, pred: P) -> Splits<'a, T, P>
+    fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P>
                     where P: FnMut(&T) -> bool;
-    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, T, P>>
+    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P>
                      where P: FnMut(&T) -> bool;
-    fn rsplitn<'a, P>(&'a self,  n: uint, pred: P) -> SplitsN<Splits<'a, T, P>>
+    fn rsplitn<'a, P>(&'a self,  n: uint, pred: P) -> RSplitN<'a, T, P>
                       where P: FnMut(&T) -> bool;
     fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>;
     fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>;
     fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
-    fn head<'a>(&'a self) -> Option<&'a T>;
+    fn first<'a>(&'a self) -> Option<&'a T>;
     fn tail<'a>(&'a self) -> &'a [T];
     fn init<'a>(&'a self) -> &'a [T];
     fn last<'a>(&'a self) -> Option<&'a T>;
-    unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T;
+    unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T;
     fn as_ptr(&self) -> *const T;
-    fn binary_search<F>(&self, f: F) -> BinarySearchResult
-                        where F: FnMut(&T) -> Ordering;
+    fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
+        F: FnMut(&T) -> Ordering;
     fn len(&self) -> uint;
     fn is_empty(&self) -> bool { self.len() == 0 }
     fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
@@ -93,21 +93,21 @@ pub trait SliceExt<T> for Sized? {
     fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T];
     fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T];
     fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>;
-    fn head_mut<'a>(&'a mut self) -> Option<&'a mut T>;
+    fn first_mut<'a>(&'a mut self) -> Option<&'a mut T>;
     fn tail_mut<'a>(&'a mut self) -> &'a mut [T];
     fn init_mut<'a>(&'a mut self) -> &'a mut [T];
     fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>;
-    fn split_mut<'a, P>(&'a mut self, pred: P) -> MutSplits<'a, T, P>
+    fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P>
                         where P: FnMut(&T) -> bool;
-    fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitsN<MutSplits<T, P>>
+    fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<T, P>
                      where P: FnMut(&T) -> bool;
-    fn rsplitn_mut<P>(&mut self,  n: uint, pred: P) -> SplitsN<MutSplits<T, P>>
+    fn rsplitn_mut<P>(&mut self,  n: uint, pred: P) -> RSplitNMut<T, P>
                       where P: FnMut(&T) -> bool;
-    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T>;
+    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T>;
     fn swap(&mut self, a: uint, b: uint);
     fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]);
     fn reverse(&mut self);
-    unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T;
+    unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T;
     fn as_mut_ptr(&mut self) -> *mut T;
 }
 
@@ -145,11 +145,11 @@ impl<T> SliceExt<T> for [T] {
         unsafe {
             let p = self.as_ptr();
             if mem::size_of::<T>() == 0 {
-                Iter{ptr: p,
+                Iter {ptr: p,
                       end: (p as uint + self.len()) as *const T,
                       marker: marker::ContravariantLifetime::<'a>}
             } else {
-                Iter{ptr: p,
+                Iter {ptr: p,
                       end: p.offset(self.len() as int),
                       marker: marker::ContravariantLifetime::<'a>}
             }
@@ -157,8 +157,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split<'a, P>(&'a self, pred: P) -> Splits<'a, T, P> where P: FnMut(&T) -> bool {
-        Splits {
+    fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P> where P: FnMut(&T) -> bool {
+        Split {
             v: self,
             pred: pred,
             finished: false
@@ -166,24 +166,28 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, T, P>> where
+    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P> where
         P: FnMut(&T) -> bool,
     {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: false
+        SplitN {
+            inner: GenericSplitN {
+                iter: self.split(pred),
+                count: n,
+                invert: false
+            }
         }
     }
 
     #[inline]
-    fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, T, P>> where
+    fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, T, P> where
         P: FnMut(&T) -> bool,
     {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: true
+        RSplitN {
+            inner: GenericSplitN {
+                iter: self.split(pred),
+                count: n,
+                invert: true
+            }
         }
     }
 
@@ -205,7 +209,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head(&self) -> Option<&T> {
+    fn first(&self) -> Option<&T> {
         if self.len() == 0 { None } else { Some(&self[0]) }
     }
 
@@ -223,7 +227,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_get(&self, index: uint) -> &T {
+    unsafe fn get_unchecked(&self, index: uint) -> &T {
         transmute(self.repr().data.offset(index as int))
     }
 
@@ -233,14 +237,16 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[unstable]
-    fn binary_search<F>(&self, mut f: F) -> BinarySearchResult where F: FnMut(&T) -> Ordering {
+    fn binary_search_by<F>(&self, mut f: F) -> Result where
+        F: FnMut(&T) -> Ordering
+    {
         let mut base : uint = 0;
         let mut lim : uint = self.len();
 
         while lim != 0 {
             let ix = base + (lim >> 1);
             match f(&self[ix]) {
-                Equal => return BinarySearchResult::Found(ix),
+                Equal => return Ok(ix),
                 Less => {
                     base = ix + 1;
                     lim -= 1;
@@ -249,7 +255,7 @@ impl<T> SliceExt<T> for [T] {
             }
             lim >>= 1;
         }
-        return BinarySearchResult::NotFound(base);
+        Err(base);
     }
 
     #[inline]
@@ -292,11 +298,11 @@ impl<T> SliceExt<T> for [T] {
         unsafe {
             let p = self.as_mut_ptr();
             if mem::size_of::<T>() == 0 {
-                IterMut{ptr: p,
+                IterMut {ptr: p,
                          end: (p as uint + self.len()) as *mut T,
                          marker: marker::ContravariantLifetime::<'a>}
             } else {
-                IterMut{ptr: p,
+                IterMut {ptr: p,
                          end: p.offset(self.len() as int),
                          marker: marker::ContravariantLifetime::<'a>}
             }
@@ -311,7 +317,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head_mut(&mut self) -> Option<&mut T> {
+    fn first_mut(&mut self) -> Option<&mut T> {
         if self.len() == 0 { None } else { Some(&mut self[0]) }
     }
 
@@ -327,36 +333,40 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split_mut<'a, P>(&'a mut self, pred: P) -> MutSplits<'a, T, P> where P: FnMut(&T) -> bool {
-        MutSplits { v: self, pred: pred, finished: false }
+    fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+        SplitMut { v: self, pred: pred, finished: false }
     }
 
     #[inline]
-    fn splitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitsN<MutSplits<'a, T, P>> where
+    fn splitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitNMut<'a, T, P> where
         P: FnMut(&T) -> bool
     {
-        SplitsN {
-            iter: self.split_mut(pred),
-            count: n,
-            invert: false
+        SplitNMut {
+            inner: GenericSplitN {
+                iter: self.split_mut(pred),
+                count: n,
+                invert: false
+            }
         }
     }
 
     #[inline]
-    fn rsplitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitsN<MutSplits<'a, T, P>> where
+    fn rsplitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> RSplitNMut<'a, T, P> where
         P: FnMut(&T) -> bool,
     {
-        SplitsN {
-            iter: self.split_mut(pred),
-            count: n,
-            invert: true
+        RSplitNMut {
+            inner: GenericSplitN {
+                iter: self.split_mut(pred),
+                count: n,
+                invert: true
+            }
         }
    }
 
     #[inline]
-    fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks<T> {
+    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T> {
         assert!(chunk_size > 0);
-        MutChunks { v: self, chunk_size: chunk_size }
+        ChunksMut { v: self, chunk_size: chunk_size }
     }
 
     fn swap(&mut self, a: uint, b: uint) {
@@ -375,8 +385,8 @@ impl<T> SliceExt<T> for [T] {
         while i < ln / 2 {
             // Unsafe swap to avoid the bounds check in safe swap.
             unsafe {
-                let pa: *mut T = self.unsafe_mut(i);
-                let pb: *mut T = self.unsafe_mut(ln - i - 1);
+                let pa: *mut T = self.get_unchecked_mut(i);
+                let pb: *mut T = self.get_unchecked_mut(ln - i - 1);
                 ptr::swap(pa, pb);
             }
             i += 1;
@@ -384,7 +394,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T {
+    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T {
         transmute((self.repr().data as *mut T).offset(index as int))
     }
 
@@ -468,21 +478,26 @@ impl<T> ops::SliceMut<uint, [T]> for [T] {
 }
 
 /// Extension methods for slices containing `PartialEq` elements.
-#[unstable = "may merge with other traits"]
+#[unstable = "may merge with SliceExt"]
 pub trait PartialEqSliceExt<T: PartialEq> for Sized? {
     /// Find the first index containing a matching value.
+    #[experimental]
     fn position_elem(&self, t: &T) -> Option<uint>;
 
     /// Find the last index containing a matching value.
+    #[experimental]
     fn rposition_elem(&self, t: &T) -> Option<uint>;
 
     /// Return true if the slice contains an element with the given value.
+    #[stable]
     fn contains(&self, x: &T) -> bool;
 
     /// Returns true if `needle` is a prefix of the slice.
+    #[stable]
     fn starts_with(&self, needle: &[T]) -> bool;
 
     /// Returns true if `needle` is a suffix of the slice.
+    #[stable]
     fn ends_with(&self, needle: &[T]) -> bool;
 }
 
@@ -520,19 +535,16 @@ impl<T: PartialEq> PartialEqSliceExt<T> for [T] {
 #[unstable = "may merge with other traits"]
 #[allow(missing_docs)] // docs in libcollections
 pub trait OrdSliceExt<T: Ord> for Sized? {
-    #[unstable = "name likely to change"]
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
-    #[experimental]
+    fn binary_search(&self, x: &T) -> Result<uint, uint>;
     fn next_permutation(&mut self) -> bool;
-    #[experimental]
     fn prev_permutation(&mut self) -> bool;
 }
 
 #[unstable = "trait is unstable"]
 impl<T: Ord> OrdSliceExt<T> for [T] {
     #[unstable]
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
-        self.binary_search(|p| p.cmp(x))
+    fn binary_search(&self, x: &T) -> Result<uint, uint> {
+        self.binary_search_by(|p| p.cmp(x))
     }
 
     #[experimental]
@@ -619,28 +631,30 @@ impl<T: Clone> CloneSliceExt<T> for [T] {
     }
 }
 
-//
+////////////////////////////////////////////////////////////////////////////////
 // Common traits
-//
+////////////////////////////////////////////////////////////////////////////////
 
 /// Data that is viewable as a slice.
-#[unstable = "may merge with other traits"]
+#[experimental = "will be replaced by slice syntax"]
 pub trait AsSlice<T> for Sized? {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a [T];
 }
 
-#[unstable = "trait is unstable"]
+#[experimental = "trait is experimental"]
 impl<T> AsSlice<T> for [T] {
     #[inline(always)]
     fn as_slice<'a>(&'a self) -> &'a [T] { self }
 }
 
+#[experimental = "trait is experimental"]
 impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
 }
 
+#[experimental = "trait is experimental"]
 impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a mut U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
@@ -656,7 +670,7 @@ impl<'a, T> Default for &'a [T] {
 // Iterators
 //
 
-// The shared definition of the `Item` and `IterMut` iterators
+// The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
     (struct $name:ident -> $ptr:ty, $elem:ty) => {
         #[experimental = "needs review"]
@@ -736,9 +750,8 @@ macro_rules! make_slice {
     }}
 }
 
-
 /// Immutable slice iterator
-#[experimental = "needs review"]
+#[stable]
 pub struct Iter<'a, T: 'a> {
     ptr: *const T,
     end: *const T,
@@ -813,7 +826,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> {
 }
 
 /// Mutable slice iterator.
-#[experimental = "needs review"]
+#[stable]
 pub struct IterMut<'a, T: 'a> {
     ptr: *mut T,
     end: *mut T,
@@ -876,9 +889,9 @@ iterator!{struct IterMut -> *mut T, &'a mut T}
 #[experimental = "needs review"]
 impl<'a, T> ExactSizeIterator<&'a mut T> for IterMut<'a, T> {}
 
-/// An abstraction over the splitting iterators, so that splitn, splitn_mut etc
-/// can be implemented once.
-trait SplitsIter<E>: DoubleEndedIterator<E> {
+/// An internal abstraction over the splitting iterators, so that
+/// splitn, splitn_mut etc can be implemented once.
+trait SplitIter<E>: DoubleEndedIterator<E> {
     /// Mark the underlying iterator as complete, extracting the remaining
     /// portion of the slice.
     fn finish(&mut self) -> Option<E>;
@@ -886,8 +899,8 @@ trait SplitsIter<E>: DoubleEndedIterator<E> {
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function.
-#[experimental = "needs review"]
-pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool {
+#[stable]
+pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a [T],
     pred: P,
     finished: bool
@@ -895,9 +908,9 @@ pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool {
 
 // FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
 #[stable]
-impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool {
-    fn clone(&self) -> Splits<'a, T, P> {
-        Splits {
+impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool {
+    fn clone(&self) -> Split<'a, T, P> {
+        Split {
             v: self.v,
             pred: self.pred.clone(),
             finished: self.finished,
@@ -906,7 +919,7 @@ impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool {
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> Iterator<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
         if self.finished { return None; }
@@ -932,7 +945,7 @@ impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
         if self.finished { return None; }
@@ -948,7 +961,7 @@ impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(
     }
 }
 
-impl<'a, T, P> SplitsIter<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> SplitIter<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn finish(&mut self) -> Option<&'a [T]> {
         if self.finished { None } else { self.finished = true; Some(self.v) }
@@ -957,14 +970,14 @@ impl<'a, T, P> SplitsIter<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bo
 
 /// An iterator over the subslices of the vector which are separated
 /// by elements that match `pred`.
-#[experimental = "needs review"]
-pub struct MutSplits<'a, T:'a, P> where P: FnMut(&T) -> bool {
+#[stable]
+pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a mut [T],
     pred: P,
     finished: bool
 }
 
-impl<'a, T, P> SplitsIter<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> SplitIter<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn finish(&mut self) -> Option<&'a mut [T]> {
         if self.finished {
@@ -977,7 +990,7 @@ impl<'a, T, P> SplitsIter<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> Iterator<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next(&mut self) -> Option<&'a mut [T]> {
         if self.finished { return None; }
@@ -1010,7 +1023,7 @@ impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T)
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where
+impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for SplitMut<'a, T, P> where
     P: FnMut(&T) -> bool,
 {
     #[inline]
@@ -1033,17 +1046,17 @@ impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where
     }
 }
 
-/// An iterator over subslices separated by elements that match a predicate
-/// function, splitting at most a fixed number of times.
-#[experimental = "needs review"]
-pub struct SplitsN<I> {
+/// An private iterator over subslices separated by elements that
+/// match a predicate function, splitting at most a fixed number of
+/// times.
+struct GenericSplitN<I> {
     iter: I,
     count: uint,
     invert: bool
 }
 
 #[experimental = "needs review"]
-impl<E, I: SplitsIter<E>> Iterator<E> for SplitsN<I> {
+impl<E, I: SplitIter<E>> Iterator<E> for GenericSplitN<I> {
     #[inline]
     fn next(&mut self) -> Option<E> {
         if self.count == 0 {
@@ -1061,6 +1074,55 @@ impl<E, I: SplitsIter<E>> Iterator<E> for SplitsN<I> {
     }
 }
 
+/// An iterator over subslices separated by elements that match a predicate
+/// function, limited to a given number of splits.
+pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<Split<'a, T, P>>
+}
+
+/// An iterator over subslices separated by elements that match a
+/// predicate function, limited to a given number of splits, starting
+/// from the end of the slice.
+pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<Split<'a, T, P>>
+}
+
+/// An iterator over subslices separated by elements that match a predicate
+/// function, limited to a given number of splits.
+pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<SplitMut<'a, T, P>>
+}
+
+/// An iterator over subslices separated by elements that match a
+/// predicate function, limited to a given number of splits, starting
+/// from the end of the slice.
+pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<SplitMut<'a, T, P>>
+}
+
+macro_rules! forward_iterator {
+    ($name:ident: $elem:ident, $iter_of:ty) => {
+        impl<'a, $elem, P> Iterator<$iter_of> for $name<'a, $elem, P> where
+            P: FnMut(&T) -> bool
+        {
+            #[inline]
+            fn next(&mut self) -> Option<$iter_of> {
+                self.inner.next()
+            }
+
+            #[inline]
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                self.inner.size_hint()
+            }
+        }
+    }
+}
+
+forward_iterator! { SplitN: T, &'a [T] }
+forward_iterator! { RSplitN: T, &'a [T] }
+forward_iterator! { SplitNMut: T, &'a mut [T] }
+forward_iterator! { RSplitNMut: T, &'a mut [T] }
+
 /// An iterator over overlapping subslices of length `size`.
 #[deriving(Clone)]
 #[experimental = "needs review"]
@@ -1172,13 +1234,13 @@ impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> {
 /// elements at a time). When the slice len is not evenly divided by the chunk
 /// size, the last slice of the iteration will be the remainder.
 #[experimental = "needs review"]
-pub struct MutChunks<'a, T:'a> {
+pub struct ChunksMut<'a, T:'a> {
     v: &'a mut [T],
     chunk_size: uint
 }
 
 #[experimental = "needs review"]
-impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
+impl<'a, T> Iterator<&'a mut [T]> for ChunksMut<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut [T]> {
         if self.v.len() == 0 {
@@ -1206,7 +1268,7 @@ impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
 }
 
 #[experimental = "needs review"]
-impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
+impl<'a, T> DoubleEndedIterator<&'a mut [T]> for ChunksMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
         if self.v.len() == 0 {
@@ -1224,51 +1286,12 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
 }
 
 
-
-/// The result of calling `binary_search`.
-///
-/// `Found` means the search succeeded, and the contained value is the
-/// index of the matching element. `NotFound` means the search
-/// succeeded, and the contained value is an index where a matching
-/// value could be inserted while maintaining sort order.
-#[deriving(Copy, PartialEq, Show)]
-#[experimental = "needs review"]
-pub enum BinarySearchResult {
-    /// The index of the found value.
-    Found(uint),
-    /// The index where the value should have been found.
-    NotFound(uint)
-}
-
-#[experimental = "needs review"]
-impl BinarySearchResult {
-    /// Converts a `Found` to `Some`, `NotFound` to `None`.
-    /// Similar to `Result::ok`.
-    pub fn found(&self) -> Option<uint> {
-        match *self {
-            BinarySearchResult::Found(i) => Some(i),
-            BinarySearchResult::NotFound(_) => None
-        }
-    }
-
-    /// Convert a `Found` to `None`, `NotFound` to `Some`.
-    /// Similar to `Result::err`.
-    pub fn not_found(&self) -> Option<uint> {
-        match *self {
-            BinarySearchResult::Found(_) => None,
-            BinarySearchResult::NotFound(i) => Some(i)
-        }
-    }
-}
-
-
-
 //
 // Free functions
 //
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable = "waiting for DST"]
+#[unstable]
 pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
     unsafe {
         transmute(RawSlice { data: s, len: 1 })
@@ -1276,7 +1299,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
 }
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable = "waiting for DST"]
+#[unstable]
 pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
     unsafe {
         let ptr: *const A = transmute(s);
@@ -1310,7 +1333,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
 /// }
 /// ```
 #[inline]
-#[unstable = "just renamed from `mod raw`"]
+#[unstable = "should be renamed to from_raw_parts"]
 pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
     transmute(RawSlice { data: *p, len: len })
 }
@@ -1322,7 +1345,7 @@ pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
 /// not being able to provide a non-aliasing guarantee of the returned mutable
 /// slice.
 #[inline]
-#[unstable = "just renamed from `mod raw`"]
+#[unstable = "jshould be renamed to from_raw_parts_mut"]
 pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
     transmute(RawSlice { data: *p as *const T, len: len })
 }
@@ -1497,39 +1520,28 @@ impl<T: PartialOrd> PartialOrd for [T] {
     }
 }
 
-/// Extension methods for immutable slices containing integers.
+/// Extension methods for slices containing integers.
 #[experimental]
-pub trait ImmutableIntSlice<U, S> for Sized? {
+pub trait IntSliceExt<U, S> for Sized? {
     /// Converts the slice to an immutable slice of unsigned integers with the same width.
     fn as_unsigned<'a>(&'a self) -> &'a [U];
     /// Converts the slice to an immutable slice of signed integers with the same width.
     fn as_signed<'a>(&'a self) -> &'a [S];
-}
 
-/// Extension methods for mutable slices containing integers.
-#[experimental]
-pub trait MutableIntSlice<U, S> for Sized?: ImmutableIntSlice<U, S> {
     /// Converts the slice to a mutable slice of unsigned integers with the same width.
     fn as_unsigned_mut<'a>(&'a mut self) -> &'a mut [U];
     /// Converts the slice to a mutable slice of signed integers with the same width.
     fn as_signed_mut<'a>(&'a mut self) -> &'a mut [S];
 }
 
-macro_rules! impl_immut_int_slice {
+macro_rules! impl_int_slice {
     ($u:ty, $s:ty, $t:ty) => {
         #[experimental]
-        impl ImmutableIntSlice<$u, $s> for [$t] {
+        impl IntSliceExt<$u, $s> for [$t] {
             #[inline]
             fn as_unsigned(&self) -> &[$u] { unsafe { transmute(self) } }
             #[inline]
             fn as_signed(&self) -> &[$s] { unsafe { transmute(self) } }
-        }
-    }
-}
-macro_rules! impl_mut_int_slice {
-    ($u:ty, $s:ty, $t:ty) => {
-        #[experimental]
-        impl MutableIntSlice<$u, $s> for [$t] {
             #[inline]
             fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute(self) } }
             #[inline]
@@ -1538,17 +1550,15 @@ macro_rules! impl_mut_int_slice {
     }
 }
 
-macro_rules! impl_int_slice {
+macro_rules! impl_int_slices {
     ($u:ty, $s:ty) => {
-        impl_immut_int_slice! { $u, $s, $u }
-        impl_immut_int_slice! { $u, $s, $s }
-        impl_mut_int_slice! { $u, $s, $u }
-        impl_mut_int_slice! { $u, $s, $s }
+        impl_int_slice! { $u, $s, $u }
+        impl_int_slice! { $u, $s, $s }
     }
 }
 
-impl_int_slice! { u8,   i8 }
-impl_int_slice! { u16,  i16 }
-impl_int_slice! { u32,  i32 }
-impl_int_slice! { u64,  i64 }
-impl_int_slice! { uint, int }
+impl_int_slices! { u8,   i8  }
+impl_int_slices! { u16,  i16 }
+impl_int_slices! { u32,  i32 }
+impl_int_slices! { u64,  i64 }
+impl_int_slices! { uint, int }
diff --git a/src/rust-installer b/src/rust-installer
-Subproject 3a37981744a5af2433fed551f742465c78c9af7
+Subproject aed73472416064642911af790b25d57c9390b6c