collections: Split the `collections` feature

This commit also deprecates the `as_string` and `as_slice` free functions in the
`string` and `vec` modules.
diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs
index 451b1fd..f620417 100644
--- a/src/libcollections/binary_heap.rs
+++ b/src/libcollections/binary_heap.rs
@@ -10,10 +10,11 @@
 
 //! A priority queue implemented with a binary heap.
 //!
-//! Insertion and popping the largest element have `O(log n)` time complexity. Checking the largest
-//! element is `O(1)`. Converting a vector to a binary heap can be done in-place, and has `O(n)`
-//! complexity. A binary heap can also be converted to a sorted vector in-place, allowing it to
-//! be used for an `O(n log n)` in-place heapsort.
+//! Insertion and popping the largest element have `O(log n)` time complexity.
+//! Checking the largest element is `O(1)`. Converting a vector to a binary heap
+//! can be done in-place, and has `O(n)` complexity. A binary heap can also be
+//! converted to a sorted vector in-place, allowing it to be used for an `O(n
+//! log n)` in-place heapsort.
 //!
 //! # Examples
 //!
@@ -539,8 +540,9 @@
     ///
     /// The elements are removed in arbitrary order.
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
+    #[unstable(feature = "drain",
+               reason = "matches collection reform specification, \
+                         waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         Drain { iter: self.data.drain(..) }
     }
@@ -678,7 +680,7 @@
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// An iterator that drains a `BinaryHeap`.
-#[unstable(feature = "collections", reason = "recent addition")]
+#[unstable(feature = "drain", reason = "recent addition")]
 pub struct Drain<'a, T: 'a> {
     iter: vec::Drain<'a, T>,
 }
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index 562bbe2..5709ed7 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -156,8 +156,7 @@
 /// println!("{:?}", bv);
 /// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
 /// ```
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitvec", reason = "RFC 509")]
 pub struct BitVec {
     /// Internal representation of the bit vector
     storage: Vec<u32>,
@@ -181,14 +180,16 @@
 
 /// Computes how many blocks are needed to store that many bits
 fn blocks_for_bits(bits: usize) -> usize {
-    // If we want 17 bits, dividing by 32 will produce 0. So we add 1 to make sure we
-    // reserve enough. But if we want exactly a multiple of 32, this will actually allocate
-    // one too many. So we need to check if that's the case. We can do that by computing if
-    // bitwise AND by `32 - 1` is 0. But LLVM should be able to optimize the semantically
-    // superior modulo operator on a power of two to this.
+    // If we want 17 bits, dividing by 32 will produce 0. So we add 1 to make
+    // sure we reserve enough. But if we want exactly a multiple of 32, this
+    // will actually allocate one too many. So we need to check if that's the
+    // case. We can do that by computing if bitwise AND by `32 - 1` is 0. But
+    // LLVM should be able to optimize the semantically superior modulo operator
+    // on a power of two to this.
     //
     // Note that we can technically avoid this branch with the expression
-    // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost usize::MAX this will overflow.
+    // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost usize::MAX
+    // this will overflow.
     if bits % u32::BITS == 0 {
         bits / u32::BITS
     } else {
@@ -202,6 +203,7 @@
     !0 >> (u32::BITS - bits % u32::BITS) % u32::BITS
 }
 
+#[unstable(feature = "bitvec", reason = "RFC 509")]
 impl BitVec {
     /// Applies the given operation to the blocks of self and other, and sets
     /// self to be the result. This relies on the caller not to corrupt the
@@ -407,8 +409,6 @@
     /// assert_eq!(bv[3], true);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "panic semantics are likely to change in the future")]
     pub fn set(&mut self, i: usize, x: bool) {
         assert!(i < self.nbits);
         let w = i / u32::BITS;
@@ -608,7 +608,7 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_vec_append_split_off)]
+    /// # #![feature(bitvec, append)]
     /// use std::collections::BitVec;
     ///
     /// let mut a = BitVec::from_bytes(&[0b10000000]);
@@ -621,7 +621,7 @@
     /// assert!(a.eq_vec(&[true, false, false, false, false, false, false, false,
     ///                    false, true, true, false, false, false, false, true]));
     /// ```
-    #[unstable(feature = "bit_vec_append_split_off",
+    #[unstable(feature = "append",
                reason = "recently added as part of collections reform 2")]
     pub fn append(&mut self, other: &mut Self) {
         let b = self.len() % u32::BITS;
@@ -651,7 +651,7 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_vec_append_split_off)]
+    /// # #![feature(bitvec, split_off)]
     /// use std::collections::BitVec;
     /// let mut a = BitVec::new();
     /// a.push(true);
@@ -666,7 +666,7 @@
     /// assert!(a.eq_vec(&[true, false]));
     /// assert!(b.eq_vec(&[false, true]));
     /// ```
-    #[unstable(feature = "bit_vec_append_split_off",
+    #[unstable(feature = "split_off",
                reason = "recently added as part of collections reform 2")]
     pub fn split_off(&mut self, at: usize) -> Self {
         assert!(at <= self.len(), "`at` out of bounds");
@@ -1254,8 +1254,7 @@
 /// assert!(bv[3]);
 /// ```
 #[derive(Clone)]
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitset", reason = "RFC 509")]
 pub struct BitSet {
     bit_vec: BitVec,
 }
@@ -1322,6 +1321,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 impl cmp::Eq for BitSet {}
 
+#[unstable(feature = "bitset", reason = "RFC 509")]
 impl BitSet {
     /// Creates a new empty `BitSet`.
     ///
@@ -1808,7 +1808,7 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_set_append_split_off)]
+    /// # #![feature(collections, append)]
     /// use std::collections::{BitVec, BitSet};
     ///
     /// let mut a = BitSet::new();
@@ -1826,7 +1826,7 @@
     /// assert_eq!(b.len(), 0);
     /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010])));
     /// ```
-    #[unstable(feature = "bit_set_append_split_off",
+    #[unstable(feature = "append",
                reason = "recently added as part of collections reform 2")]
     pub fn append(&mut self, other: &mut Self) {
         self.union_with(other);
@@ -1839,7 +1839,7 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections, bit_set_append_split_off)]
+    /// # #![feature(bitset, split_off)]
     /// use std::collections::{BitSet, BitVec};
     /// let mut a = BitSet::new();
     /// a.insert(2);
@@ -1854,7 +1854,7 @@
     /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100000])));
     /// assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010010])));
     /// ```
-    #[unstable(feature = "bit_set_append_split_off",
+    #[unstable(feature = "split_off",
                reason = "recently added as part of collections reform 2")]
     pub fn split_off(&mut self, at: usize) -> Self {
         let mut other = BitSet::new();
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 314036e..127f470 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -1520,7 +1520,7 @@
     /// }
     /// assert_eq!(Some((&5, &"b")), map.range(Included(&4), Unbounded).next());
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range<'a>(&'a self, min: Bound<&K>, max: Bound<&K>) -> Range<'a, K, V> {
         range_impl!(&self.root, min, max, as_slices_internal, iter, Range, edges, [])
@@ -1548,7 +1548,7 @@
     ///     println!("{} => {}", name, balance);
     /// }
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range_mut<'a>(&'a mut self, min: Bound<&K>, max: Bound<&K>) -> RangeMut<'a, K, V> {
         range_impl!(&mut self.root, min, max, as_slices_internal_mut, iter_mut, RangeMut,
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index ec6c5e6..5914e2f 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -102,7 +102,7 @@
     /// Makes a new BTreeSet with the given B.
     ///
     /// B cannot be less than 2.
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_b",
                reason = "probably want this to be on the type, eventually")]
     pub fn with_b(b: usize) -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::with_b(b) }
@@ -154,7 +154,7 @@
     /// }
     /// assert_eq!(Some(&5), set.range(Included(&4), Unbounded).next());
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "btree_range",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn range<'a>(&'a self, min: Bound<&T>, max: Bound<&T>) -> Range<'a, T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index ad90f9f..e90e6c0 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -13,21 +13,26 @@
 //! This module defines a container which uses an efficient bit mask
 //! representation to hold C-like enum variants.
 
+#![unstable(feature = "enumset",
+            reason = "matches collection reform specification, \
+                      waiting for dust to settle")]
+
 use core::prelude::*;
 use core::marker;
 use core::fmt;
 use core::iter::{FromIterator};
 use core::ops::{Sub, BitOr, BitAnd, BitXor};
 
-// FIXME(contentions): implement union family of methods? (general design may be wrong here)
+// FIXME(contentions): implement union family of methods? (general design may be
+// wrong here)
 
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
 /// A specialized set implementation to use enum types.
 ///
-/// It is a logic error for an item to be modified in such a way that the transformation of the
-/// item to or from a `usize`, as determined by the `CLike` trait, changes while the item is in the
-/// set. This is normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe
-/// code.
+/// It is a logic error for an item to be modified in such a way that the
+/// transformation of the item to or from a `usize`, as determined by the
+/// `CLike` trait, changes while the item is in the set. This is normally only
+/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct EnumSet<E> {
     // We must maintain the invariant that no bits are set
     // for which no variant exists
@@ -93,22 +98,16 @@
 
 impl<E:CLike> EnumSet<E> {
     /// Returns an empty `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn new() -> EnumSet<E> {
         EnumSet {bits: 0, marker: marker::PhantomData}
     }
 
     /// Returns the number of elements in the given `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn len(&self) -> usize {
         self.bits.count_ones() as usize
     }
 
     /// Returns true if the `EnumSet` is empty.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_empty(&self) -> bool {
         self.bits == 0
     }
@@ -118,22 +117,16 @@
     }
 
     /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_disjoint(&self, other: &EnumSet<E>) -> bool {
         (self.bits & other.bits) == 0
     }
 
     /// Returns `true` if a given `EnumSet` is included in this `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_superset(&self, other: &EnumSet<E>) -> bool {
         (self.bits & other.bits) == other.bits
     }
 
     /// Returns `true` if this `EnumSet` is included in the given `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn is_subset(&self, other: &EnumSet<E>) -> bool {
         other.is_superset(self)
     }
@@ -151,8 +144,6 @@
     }
 
     /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn insert(&mut self, e: E) -> bool {
         let result = !self.contains(&e);
         self.bits |= bit(&e);
@@ -160,8 +151,6 @@
     }
 
     /// Removes an enum from the EnumSet
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn remove(&mut self, e: &E) -> bool {
         let result = self.contains(e);
         self.bits &= !bit(e);
@@ -169,15 +158,11 @@
     }
 
     /// Returns `true` if an `EnumSet` contains a given enum.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn contains(&self, e: &E) -> bool {
         (self.bits & bit(e)) != 0
     }
 
     /// Returns an iterator over an `EnumSet`.
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn iter(&self) -> Iter<E> {
         Iter::new(self.bits)
     }
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index ecf5bac..9762381 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -10,14 +10,17 @@
 
 //! Collection types.
 //!
-//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.
+//! See [std::collections](../std/collections) for a detailed discussion of
+//! collections in Rust.
 
 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
 #![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "collections"]
-#![unstable(feature = "collections")]
 #![staged_api]
 #![crate_type = "rlib"]
+#![unstable(feature = "collections",
+            reason = "library is unlikely to be stabilized with the current \
+                      layout and name, use std::collections instead")]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
@@ -107,14 +110,12 @@
 pub mod vec_deque;
 pub mod vec_map;
 
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitvec", reason = "RFC 509")]
 pub mod bit_vec {
     pub use bit::{BitVec, Iter};
 }
 
-#[unstable(feature = "collections",
-           reason = "RFC 509")]
+#[unstable(feature = "bitset", reason = "RFC 509")]
 pub mod bit_set {
     pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
     pub use bit::SetIter as Iter;
@@ -133,6 +134,7 @@
 
 // FIXME(#14344) this shouldn't be necessary
 #[doc(hidden)]
+#[unstable(feature = "issue_14344_fixme")]
 pub fn fixme_14344_be_sure_to_link_to_collections() {}
 
 #[cfg(not(test))]
@@ -141,6 +143,7 @@
 }
 
 /// An endpoint of a range of keys.
+#[unstable(feature = "collections_bound")]
 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
 pub enum Bound<T> {
     /// An inclusive bound.
diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs
index 8ff49ef..a732ce9 100644
--- a/src/libcollections/linked_list.rs
+++ b/src/libcollections/linked_list.rs
@@ -801,7 +801,7 @@
     /// }
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "linked_list_extras",
                reason = "this is probably better handled by a cursor type -- we'll see")]
     pub fn insert_next(&mut self, elt: A) {
         self.insert_next_node(box Node::new(elt))
@@ -824,7 +824,7 @@
     /// assert_eq!(it.next().unwrap(), &2);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "linked_list_extras",
                reason = "this is probably better handled by a cursor type -- we'll see")]
     pub fn peek_next(&mut self) -> Option<&mut A> {
         if self.nelem == 0 {
diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs
index 6ab1439..f37c4ae 100644
--- a/src/libcollections/range.rs
+++ b/src/libcollections/range.rs
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+
 #![unstable(feature = "collections_range", reason = "was just added")]
 
 //! Range syntax.
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 3106527..c5418c9 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -11,7 +11,8 @@
 //! Utilities for slice manipulation
 //!
 //! The `slice` module contains useful code to help work with slice values.
-//! Slices are a view into a block of memory represented as a pointer and a length.
+//! Slices are a view into a block of memory represented as a pointer and a
+//! length.
 //!
 //! ```
 //! // slicing a Vec
@@ -69,8 +70,9 @@
 //! }
 //! ```
 //!
-//! This iterator yields mutable references to the slice's elements, so while the element
-//! type of the slice is `i32`, the element type of the iterator is `&mut i32`.
+//! This iterator yields mutable references to the slice's elements, so while
+//! the element type of the slice is `i32`, the element type of the iterator is
+//! `&mut i32`.
 //!
 //! * `.iter()` and `.iter_mut()` are the explicit methods to return the default
 //!   iterators.
@@ -278,14 +280,14 @@
     }
 
     /// Returns all but the first element of a slice.
-    #[unstable(feature = "collections", reason = "likely to be renamed")]
+    #[unstable(feature = "slice_extras", reason = "likely to be renamed")]
     #[inline]
     pub fn tail(&self) -> &[T] {
         core_slice::SliceExt::tail(self)
     }
 
     /// Returns all but the first element of a mutable slice
-    #[unstable(feature = "collections",
+    #[unstable(feature = "slice_extras",
                reason = "likely to be renamed or removed")]
     #[inline]
     pub fn tail_mut(&mut self) -> &mut [T] {
@@ -293,14 +295,14 @@
     }
 
     /// Returns all but the last element of a slice.
-    #[unstable(feature = "collections", reason = "likely to be renamed")]
+    #[unstable(feature = "slice_extras", reason = "likely to be renamed")]
     #[inline]
     pub fn init(&self) -> &[T] {
         core_slice::SliceExt::init(self)
     }
 
     /// Returns all but the last element of a mutable slice
-    #[unstable(feature = "collections",
+    #[unstable(feature = "slice_extras",
                reason = "likely to be renamed or removed")]
     #[inline]
     pub fn init_mut(&mut self) -> &mut [T] {
@@ -727,13 +729,13 @@
     }
 
     /// Find the first index containing a matching value.
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "slice_position_elem")]
     pub fn position_elem(&self, t: &T) -> Option<usize> where T: PartialEq {
         core_slice::SliceExt::position_elem(self, t)
     }
 
     /// Find the last index containing a matching value.
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "slice_position_elem")]
     pub fn rposition_elem(&self, t: &T) -> Option<usize> where T: PartialEq {
         core_slice::SliceExt::rposition_elem(self, t)
     }
@@ -869,7 +871,7 @@
     /// assert_eq!(Some(vec![1, 3, 2]), perms.next());
     /// assert_eq!(Some(vec![3, 1, 2]), perms.next());
     /// ```
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "permutations")]
     #[inline]
     pub fn permutations(&self) -> Permutations<T> where T: Clone {
         // NB see hack module in this file
@@ -893,7 +895,7 @@
     /// let b: &mut [_] = &mut [1, 0, 2];
     /// assert!(v == b);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "permutations",
                reason = "uncertain if this merits inclusion in std")]
     pub fn next_permutation(&mut self) -> bool where T: Ord {
         core_slice::SliceExt::next_permutation(self)
@@ -916,7 +918,7 @@
     /// let b: &mut [_] = &mut [0, 1, 2];
     /// assert!(v == b);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "permutations",
                reason = "uncertain if this merits inclusion in std")]
     pub fn prev_permutation(&mut self) -> bool where T: Ord {
         core_slice::SliceExt::prev_permutation(self)
@@ -940,7 +942,7 @@
     /// assert!(dst.clone_from_slice(&src2) == 3);
     /// assert!(dst == [3, 4, 5]);
     /// ```
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "clone_from_slice")]
     pub fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone {
         core_slice::SliceExt::clone_from_slice(self, src)
     }
@@ -967,7 +969,7 @@
     /// assert_eq!(num_moved, 3);
     /// assert!(a == [6, 7, 8, 4, 5]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "move_from",
                reason = "uncertain about this API approach")]
     #[inline]
     pub fn move_from(&mut self, mut src: Vec<T>, start: usize, end: usize) -> usize {
@@ -997,10 +999,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
-#[unstable(feature = "collections", reason = "recently changed")]
+#[unstable(feature = "slice_concat_ext",
+           reason = "trait should not have to exist")]
 /// An extension trait for concatenating slices
 pub trait SliceConcatExt<T: ?Sized> {
-    #[unstable(feature = "collections", reason = "recently changed")]
+    #[unstable(feature = "slice_concat_ext",
+               reason = "trait should not have to exist")]
     /// The resulting type after concatenation
     type Output;
 
@@ -1014,8 +1018,8 @@
     #[stable(feature = "rust1", since = "1.0.0")]
     fn concat(&self) -> Self::Output;
 
-    /// Flattens a slice of `T` into a single value `Self::Output`, placing a given separator
-    /// between each.
+    /// Flattens a slice of `T` into a single value `Self::Output`, placing a
+    /// given separator between each.
     ///
     /// # Examples
     ///
@@ -1060,7 +1064,7 @@
 ///
 /// The last generated swap is always (0, 1), and it returns the
 /// sequence to its initial order.
-#[unstable(feature = "collections")]
+#[unstable(feature = "permutations")]
 #[derive(Clone)]
 pub struct ElementSwaps {
     sdir: Vec<SizeDirection>,
@@ -1072,7 +1076,7 @@
 
 impl ElementSwaps {
     /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "permutations")]
     pub fn new(length: usize) -> ElementSwaps {
         // Initialize `sdir` with a direction that position should move in
         // (all negative at the beginning) and the `size` of the
@@ -1194,13 +1198,13 @@
 /// swap applied.
 ///
 /// Generates even and odd permutations alternately.
-#[unstable(feature = "collections")]
+#[unstable(feature = "permutations")]
 pub struct Permutations<T> {
     swaps: ElementSwaps,
     v: Vec<T>,
 }
 
-#[unstable(feature = "collections", reason = "trait is unstable")]
+#[unstable(feature = "permutations", reason = "trait is unstable")]
 impl<T: Clone> Iterator for Permutations<T> {
     type Item = Vec<T>;
 
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 39e1812..61e09a2 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -366,7 +366,7 @@
 ///
 /// For use with the `std::iter` module.
 #[derive(Clone)]
-#[unstable(feature = "collections")]
+#[unstable(feature = "str_utf16")]
 pub struct Utf16Units<'a> {
     encoder: Utf16Encoder<Chars<'a>>
 }
@@ -591,7 +591,7 @@
     /// assert_eq!(s.slice_chars(0, 4), "Löwe");
     /// assert_eq!(s.slice_chars(5, 7), "老虎");
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "slice_chars",
                reason = "may have yet to prove its worth")]
     pub fn slice_chars(&self, begin: usize, end: usize) -> &str {
         core_str::StrExt::slice_chars(self, begin, end)
@@ -1068,7 +1068,7 @@
     }
 
     /// Returns an iterator of `u16` over the string encoded as UTF-16.
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_utf16",
                reason = "this functionality may only be provided by libunicode")]
     pub fn utf16_units(&self) -> Utf16Units {
         Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
@@ -1527,7 +1527,7 @@
     /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
     /// assert_eq!(v, ["1", "2", "3"]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_matches",
                reason = "method got recently added")]
     pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
         core_str::StrExt::matches(self, pat)
@@ -1560,7 +1560,7 @@
     /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
     /// assert_eq!(v, ["3", "2", "1"]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_matches",
                reason = "method got recently added")]
     pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
         where P::Searcher: ReverseSearcher<'a>
@@ -1605,7 +1605,7 @@
     /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
     /// assert_eq!(v, [(0, 3)]); // only the first `aba`
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_matches",
                reason = "might have its iterator type changed")]
     // NB: Right now MatchIndices yields `(usize, usize)`, but it would
     // be more consistent with `matches` and `char_indices` to return `(usize, &str)`
@@ -1649,7 +1649,7 @@
     /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
     /// assert_eq!(v, [(2, 5)]); // only the last `aba`
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_matches",
                reason = "might have its iterator type changed")]
     // NB: Right now RMatchIndices yields `(usize, usize)`, but it would
     // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
@@ -1677,7 +1677,7 @@
     /// assert!(string.subslice_offset(lines[1]) == 2); // &"b"
     /// assert!(string.subslice_offset(lines[2]) == 4); // &"c"
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "subslice_offset",
                reason = "awaiting convention about comparability of arbitrary slices")]
     pub fn subslice_offset(&self, inner: &str) -> usize {
         core_str::StrExt::subslice_offset(self, inner)
@@ -1922,14 +1922,14 @@
     }
 
     /// Escapes each char in `s` with `char::escape_default`.
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_escape",
                reason = "return type may change to be an iterator")]
     pub fn escape_default(&self) -> String {
         self.chars().flat_map(|c| c.escape_default()).collect()
     }
 
     /// Escapes each char in `s` with `char::escape_unicode`.
-    #[unstable(feature = "collections",
+    #[unstable(feature = "str_escape",
                reason = "return type may change to be an iterator")]
     pub fn escape_unicode(&self) -> String {
         self.chars().flat_map(|c| c.escape_unicode()).collect()
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 6717f2f..6e37a57 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -696,7 +696,7 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections_drain)]
+    /// # #![feature(drain)]
     ///
     /// let mut s = String::from("α is alpha, β is beta");
     /// let beta_offset = s.find('β').unwrap_or(s.len());
@@ -710,7 +710,7 @@
     /// s.drain(..);
     /// assert_eq!(s, "");
     /// ```
-    #[unstable(feature = "collections_drain",
+    #[unstable(feature = "drain",
                reason = "recently added, matches RFC")]
     pub fn drain<R>(&mut self, range: R) -> Drain where R: RangeArgument<usize> {
         // Memory safety
@@ -975,10 +975,14 @@
 
 /// Wrapper type providing a `&String` reference via `Deref`.
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 pub struct DerefString<'a> {
     x: DerefVec<'a, u8>
 }
 
+#[allow(deprecated)]
 impl<'a> Deref for DerefString<'a> {
     type Target = String;
 
@@ -1005,6 +1009,9 @@
 /// string_consumer(&as_string("foo"));
 /// ```
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
     DerefString { x: as_vec(x.as_bytes()) }
 }
@@ -1134,7 +1141,7 @@
 }
 
 /// A draining iterator for `String`.
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 pub struct Drain<'a> {
     /// Will be used as &'a mut String in the destructor
     string: *mut String,
@@ -1149,7 +1156,7 @@
 unsafe impl<'a> Sync for Drain<'a> {}
 unsafe impl<'a> Send for Drain<'a> {}
 
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 impl<'a> Drop for Drain<'a> {
     fn drop(&mut self) {
         unsafe {
@@ -1163,7 +1170,7 @@
     }
 }
 
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 impl<'a> Iterator for Drain<'a> {
     type Item = char;
 
@@ -1177,7 +1184,7 @@
     }
 }
 
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 impl<'a> DoubleEndedIterator for Drain<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<char> {
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index ba41f43..1409ece 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -276,7 +276,7 @@
     /// the buffer are copied into the vector without cloning, as if
     /// `ptr::read()` were called on them.
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "vec_from_raw_buf",
                reason = "may be better expressed via composition")]
     pub unsafe fn from_raw_buf(ptr: *const T, elts: usize) -> Vec<T> {
         let mut dst = Vec::with_capacity(elts);
@@ -704,7 +704,7 @@
     /// assert_eq!(vec2, []);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "append",
                reason = "new API, waiting for dust to settle")]
     pub fn append(&mut self, other: &mut Self) {
         if mem::size_of::<T>() == 0 {
@@ -742,7 +742,7 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections_drain)]
+    /// # #![feature(drain)]
     ///
     /// // Draining using `..` clears the whole vector.
     /// let mut v = vec![1, 2, 3];
@@ -750,7 +750,7 @@
     /// assert_eq!(v, &[]);
     /// assert_eq!(u, &[1, 2, 3]);
     /// ```
-    #[unstable(feature = "collections_drain",
+    #[unstable(feature = "drain",
                reason = "recently added, matches RFC")]
     pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
         // Memory safety
@@ -851,7 +851,7 @@
     /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
     /// assert_eq!(&newtyped_bytes[..], &[Newtype(0x11), Newtype(0x22)]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "map_in_place",
                reason = "API may change to provide stronger guarantees")]
     pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
         // FIXME: Assert statically that the types `T` and `U` have the same
@@ -1043,14 +1043,14 @@
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// # #![feature(split_off)]
     /// let mut vec = vec![1,2,3];
     /// let vec2 = vec.split_off(1);
     /// assert_eq!(vec, [1]);
     /// assert_eq!(vec2, [2, 3]);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "split_off",
                reason = "new API, waiting for dust to settle")]
     pub fn split_off(&mut self, at: usize) -> Self {
         assert!(at <= self.len(), "`at` out of bounds");
@@ -1091,7 +1091,7 @@
     /// vec.resize(2, 0);
     /// assert_eq!(vec, [1, 2]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "vec_resize",
                reason = "matches collection reform specification; waiting for dust to settle")]
     pub fn resize(&mut self, new_len: usize, value: T) {
         let len = self.len();
@@ -1117,7 +1117,7 @@
     /// assert_eq!(vec, [1, 2, 3, 4]);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "vec_push_all",
                reason = "likely to be replaced by a more optimized extend")]
     pub fn push_all(&mut self, other: &[T]) {
         self.reserve(other.len());
@@ -1738,7 +1738,7 @@
 impl<T> IntoIter<T> {
     #[inline]
     /// Drops all items that have not yet been moved and returns the empty vector.
-    #[unstable(feature = "collections")]
+    #[unstable(feature = "iter_to_vec")]
     pub fn into_inner(mut self) -> Vec<T> {
         unsafe {
             for _x in self.by_ref() { }
@@ -1832,7 +1832,7 @@
 }
 
 /// A draining iterator for `Vec<T>`.
-#[unstable(feature = "collections_drain", reason = "recently added")]
+#[unstable(feature = "drain", reason = "recently added")]
 pub struct Drain<'a, T: 'a> {
     /// Index of tail to preserve
     tail_start: usize,
@@ -1907,12 +1907,17 @@
 
 /// Wrapper type providing a `&Vec<T>` reference via `Deref`.
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
 pub struct DerefVec<'a, T:'a> {
     x: Vec<T>,
     l: PhantomData<&'a T>,
 }
 
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 impl<'a, T> Deref for DerefVec<'a, T> {
     type Target = Vec<T>;
 
@@ -1923,6 +1928,9 @@
 
 // Prevent the inner `Vec<T>` from attempting to deallocate memory.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 impl<'a, T> Drop for DerefVec<'a, T> {
     fn drop(&mut self) {
         self.x.len = 0;
@@ -1948,6 +1956,9 @@
 /// vec_consumer(&as_vec(&values));
 /// ```
 #[unstable(feature = "collections")]
+#[deprecated(since = "1.2.0",
+             reason = "replaced with deref coercions or Borrow")]
+#[allow(deprecated)]
 pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
     unsafe {
         DerefVec {
diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs
index da13684..54127ea 100644
--- a/src/libcollections/vec_deque.rs
+++ b/src/libcollections/vec_deque.rs
@@ -491,7 +491,7 @@
     /// assert_eq!(buf.len(), 1);
     /// assert_eq!(Some(&5), buf.get(0));
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification; waiting on panic semantics")]
     pub fn truncate(&mut self, len: usize) {
         for _ in len..self.len() {
@@ -552,7 +552,7 @@
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn as_slices(&self) -> (&[T], &[T]) {
         unsafe {
@@ -572,7 +572,7 @@
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
         unsafe {
@@ -638,7 +638,7 @@
     /// assert!(v.is_empty());
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
         Drain {
@@ -880,7 +880,7 @@
     /// buf.push_back(10);
     /// assert_eq!(buf.swap_back_remove(1), Some(99));
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "the naming of this function may be altered")]
     pub fn swap_back_remove(&mut self, index: usize) -> Option<T> {
         let length = self.len();
@@ -914,7 +914,7 @@
     /// buf.push_back(20);
     /// assert_eq!(buf.swap_front_remove(3), Some(99));
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "the naming of this function may be altered")]
     pub fn swap_front_remove(&mut self, index: usize) -> Option<T> {
         let length = self.len();
@@ -1320,7 +1320,7 @@
     /// assert_eq!(buf2.len(), 2);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "split_off",
                reason = "new API, waiting for dust to settle")]
     pub fn split_off(&mut self, at: usize) -> Self {
         let len = self.len();
@@ -1383,7 +1383,7 @@
     /// assert_eq!(buf2.len(), 0);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
+    #[unstable(feature = "append",
                reason = "new API, waiting for dust to settle")]
     pub fn append(&mut self, other: &mut Self) {
         // naive impl
@@ -1447,7 +1447,7 @@
     ///     assert_eq!(a, b);
     /// }
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "deque_extras",
                reason = "matches collection reform specification; waiting on panic semantics")]
     pub fn resize(&mut self, new_len: usize, value: T) {
         let len = self.len();
@@ -1635,7 +1635,7 @@
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// A draining VecDeque iterator
-#[unstable(feature = "collections",
+#[unstable(feature = "drain",
            reason = "matches collection reform specification, waiting for dust to settle")]
 pub struct Drain<'a, T: 'a> {
     inner: &'a mut VecDeque<T>,
diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs
index 5c2f575..3fd2455 100644
--- a/src/libcollections/vec_map.rs
+++ b/src/libcollections/vec_map.rs
@@ -12,6 +12,8 @@
 //! are O(highest integer key).
 
 #![allow(missing_docs)]
+#![unstable(feature = "vecmap",
+            reason = "may not be stabilized in the standard library")]
 
 use self::Entry::*;
 
@@ -325,7 +327,7 @@
     /// assert_eq!(a[3], "c");
     /// assert_eq!(a[4], "d");
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "append",
                reason = "recently added as part of collections reform 2")]
     pub fn append(&mut self, other: &mut Self) {
         self.extend(other.drain());
@@ -358,7 +360,7 @@
     /// assert_eq!(b[3], "c");
     /// assert_eq!(b[4], "d");
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "split_off",
                reason = "recently added as part of collections reform 2")]
     pub fn split_off(&mut self, at: usize) -> Self {
         let mut other = VecMap::new();
@@ -410,7 +412,7 @@
     ///
     /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
     /// ```
-    #[unstable(feature = "collections",
+    #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain<'a>(&'a mut self) -> Drain<'a, V> {
         fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
@@ -632,7 +634,7 @@
 
 
 impl<'a, V> Entry<'a, V> {
-    #[unstable(feature = "collections",
+    #[unstable(feature = "entry",
                reason = "will soon be replaced by or_insert")]
     #[deprecated(since = "1.0",
                 reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")]
@@ -644,7 +646,7 @@
         }
     }
 
-    #[unstable(feature = "collections",
+    #[unstable(feature = "entry",
                reason = "matches entry v3 specification, waiting for dust to settle")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
@@ -655,7 +657,7 @@
         }
     }
 
-    #[unstable(feature = "collections",
+    #[unstable(feature = "entry",
                reason = "matches entry v3 specification, waiting for dust to settle")]
     /// Ensures a value is in the entry by inserting the result of the default function if empty,
     /// and returns a mutable reference to the value in the entry.
@@ -1003,14 +1005,14 @@
     fn((usize, Option<V>)) -> Option<(usize, V)>>
 }
 
-#[unstable(feature = "collections")]
+#[unstable(feature = "drain")]
 pub struct Drain<'a, V:'a> {
     iter: FilterMap<
     Enumerate<vec::Drain<'a, Option<V>>>,
     fn((usize, Option<V>)) -> Option<(usize, V)>>
 }
 
-#[unstable(feature = "collections")]
+#[unstable(feature = "drain")]
 impl<'a, V> Iterator for Drain<'a, V> {
     type Item = (usize, V);
 
@@ -1018,7 +1020,7 @@
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
-#[unstable(feature = "collections")]
+#[unstable(feature = "drain")]
 impl<'a, V> DoubleEndedIterator for Drain<'a, V> {
     fn next_back(&mut self) -> Option<(usize, V)> { self.iter.next_back() }
 }