diff --git a/mk/crates.mk b/mk/crates.mk
index 9b252267aba..cea9133e835 100644
--- a/mk/crates.mk
+++ b/mk/crates.mk
@@ -60,36 +60,36 @@ DEPS_core :=
 DEPS_rlibc :=
 DEPS_alloc := core libc native:jemalloc
 DEPS_debug := std
-DEPS_std := core rand libc alloc native:rustrt native:backtrace
+DEPS_std := core rand libc alloc collections native:rustrt native:backtrace
 DEPS_graphviz := std
 DEPS_green := std native:context_switch
 DEPS_rustuv := std native:uv native:uv_support
 DEPS_native := std
-DEPS_syntax := std term serialize collections log fmt_macros debug
+DEPS_syntax := std term serialize log fmt_macros debug
 DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
-              collections time log graphviz debug
-DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \
+              time log graphviz debug
+DEPS_rustdoc := rustc native:hoedown serialize sync getopts \
                 test time debug
 DEPS_flate := std native:miniz
-DEPS_arena := std collections
+DEPS_arena := std
 DEPS_graphviz := std
 DEPS_glob := std
-DEPS_serialize := std collections log
-DEPS_term := std collections log
+DEPS_serialize := std log
+DEPS_term := std log
 DEPS_semver := std
 DEPS_uuid := std serialize
 DEPS_sync := std alloc
 DEPS_getopts := std
-DEPS_collections := std debug
+DEPS_collections := core alloc
 DEPS_fourcc := syntax std
 DEPS_hexfloat := syntax std
 DEPS_num := std
-DEPS_test := std collections getopts serialize term time regex
+DEPS_test := std getopts serialize term time regex
 DEPS_time := std serialize sync
 DEPS_rand := core
-DEPS_url := std collections
+DEPS_url := std
 DEPS_log := std sync
-DEPS_regex := std collections
+DEPS_regex := std
 DEPS_regex_macros = syntax std regex
 DEPS_fmt_macros = std
 
@@ -105,6 +105,7 @@ ONLY_RLIB_libc := 1
 ONLY_RLIB_rlibc := 1
 ONLY_RLIB_alloc := 1
 ONLY_RLIB_rand := 1
+ONLY_RLIB_collections := 1
 
 ################################################################################
 # You should not need to edit below this line
diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs
index c91a5289faa..6cd3616fc71 100644
--- a/src/libcollections/bitv.rs
+++ b/src/libcollections/bitv.rs
@@ -10,14 +10,17 @@
 
 #![allow(missing_doc)]
 
+use core::prelude::*;
 
-use std::cmp;
-use std::fmt;
-use std::iter::RandomAccessIterator;
-use std::iter::{Enumerate, Repeat, Map, Zip};
-use std::ops;
-use std::slice;
-use std::uint;
+use core::cmp;
+use core::fmt;
+use core::iter::{Enumerate, Repeat, Map, Zip};
+use core::ops;
+use core::slice;
+use core::uint;
+
+use string::String;
+use vec::Vec;
 
 #[deriving(Clone)]
 struct SmallBitv {
diff --git a/src/libcollections/btree.rs b/src/libcollections/btree.rs
index cebf21ee7e7..d589aa73a52 100644
--- a/src/libcollections/btree.rs
+++ b/src/libcollections/btree.rs
@@ -18,8 +18,13 @@
 ///a length (the height of the tree), and lower and upper bounds on the
 ///number of elements that a given node can contain.
 
-use std::fmt;
-use std::fmt::Show;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::fmt;
+use core::fmt::Show;
+
+use vec::Vec;
 
 #[allow(missing_doc)]
 pub struct BTree<K, V> {
diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs
index fa2cb233873..b4930173bb6 100644
--- a/src/libcollections/deque.rs
+++ b/src/libcollections/deque.rs
@@ -10,7 +10,7 @@
 
 //! Container traits for collections
 
-use std::container::Mutable;
+use core::prelude::*;
 
 /// A double-ended sequence that allows querying, insertion and deletion at both ends.
 pub trait Deque<T> : Mutable {
diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs
index 014d4e680ee..062e94d21c0 100644
--- a/src/libcollections/dlist.rs
+++ b/src/libcollections/dlist.rs
@@ -21,9 +21,12 @@
 // Backlinks over DList::prev are raw pointers that form a full chain in
 // the reverse direction.
 
-use std::iter;
-use std::mem;
-use std::ptr;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::iter;
+use core::mem;
+use core::ptr;
 
 use deque::Deque;
 
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index 78485321aa5..856aff64b6a 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -13,7 +13,9 @@
 //! This module defines a container which uses an efficient bit mask
 //! representation to hold C-like enum variants.
 
-use std::num::Bitwise;
+use core::prelude::*;
+
+use core::num::Bitwise;
 
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 /// A specialized Set implementation to use enum types.
diff --git a/src/libstd/hash/mod.rs b/src/libcollections/hash/mod.rs
similarity index 93%
rename from src/libstd/hash/mod.rs
rename to src/libcollections/hash/mod.rs
index 8e95263d48e..067f266f63f 100644
--- a/src/libstd/hash/mod.rs
+++ b/src/libcollections/hash/mod.rs
@@ -63,22 +63,17 @@
 
 #![allow(unused_must_use)]
 
-use container::Container;
-use intrinsics::TypeId;
-use iter::Iterator;
-use option::{Option, Some, None};
-use owned::Box;
-use rc::Rc;
-use result::{Result, Ok, Err};
-use slice::{Vector, ImmutableVector};
-use str::{Str, StrSlice};
+use core::prelude::*;
+
+use alloc::owned::Box;
+use alloc::rc::Rc;
+use core::intrinsics::TypeId;
+
 use vec::Vec;
 
 /// Reexport the `sip::hash` function as our default hasher.
 pub use hash = self::sip::hash;
 
-pub use Writer = io::Writer;
-
 pub mod sip;
 
 /// A trait that represents a hashable type. The `S` type parameter is an
@@ -96,33 +91,29 @@ pub trait Hasher<S> {
     fn hash<T: Hash<S>>(&self, value: &T) -> u64;
 }
 
+pub trait Writer {
+    fn write(&mut self, bytes: &[u8]);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 macro_rules! impl_hash(
-    ( $( $ty:ty => $method:ident;)* ) => (
+    ( $($ty:ident)* ) => (
         $(
             impl<S: Writer> Hash<S> for $ty {
                 #[inline]
                 fn hash(&self, state: &mut S) {
-                    state.$method(*self);
+                    let a: [u8, ..::core::$ty::BYTES] = unsafe {
+                        ::core::mem::transmute(*self)
+                    };
+                    state.write(a.as_slice())
                 }
             }
         )*
     )
 )
 
-impl_hash!(
-    u8 => write_u8;
-    u16 => write_le_u16;
-    u32 => write_le_u32;
-    u64 => write_le_u64;
-    uint => write_le_uint;
-    i8 => write_i8;
-    i16 => write_le_i16;
-    i32 => write_le_i32;
-    i64 => write_le_i64;
-    int => write_le_int;
-)
+impl_hash!( u8 u16 u32 u64 uint i8 i16 i32 i64 int )
 
 impl<S: Writer> Hash<S> for bool {
     #[inline]
@@ -142,7 +133,7 @@ impl<'a, S: Writer> Hash<S> for &'a str {
     #[inline]
     fn hash(&self, state: &mut S) {
         state.write(self.as_bytes());
-        state.write_u8(0xFF);
+        0xffu8.hash(state)
     }
 }
 
diff --git a/src/libstd/hash/sip.rs b/src/libcollections/hash/sip.rs
similarity index 88%
rename from src/libstd/hash/sip.rs
rename to src/libcollections/hash/sip.rs
index 90767908612..039aee7347b 100644
--- a/src/libstd/hash/sip.rs
+++ b/src/libcollections/hash/sip.rs
@@ -24,17 +24,11 @@
  * discouraged.
  */
 
-use clone::Clone;
-use container::Container;
-use default::Default;
-use int;
-use io::{IoResult, Writer};
-use iter::Iterator;
-use result::Ok;
-use slice::ImmutableVector;
-use uint;
+use core::prelude::*;
 
-use super::{Hash, Hasher};
+use core::default::Default;
+
+use super::{Hash, Hasher, Writer};
 
 /// `SipState` computes a SipHash 2-4 hash over a stream of bytes.
 pub struct SipState {
@@ -151,41 +145,11 @@ impl SipState {
 
         v0 ^ v1 ^ v2 ^ v3
     }
-
-    #[inline]
-    fn write_le(&mut self, n: u64, size: uint) {
-        self.tail |= n << 8*self.ntail;
-        self.ntail += size;
-
-        if self.ntail >= 8 {
-            let m = self.tail;
-
-            self.v3 ^= m;
-            compress!(self.v0, self.v1, self.v2, self.v3);
-            compress!(self.v0, self.v1, self.v2, self.v3);
-            self.v0 ^= m;
-
-            self.ntail -= 8;
-            if self.ntail == 0 {
-                self.tail = 0;
-            } else {
-                self.tail = n >> 64 - 8*self.ntail;
-            }
-        }
-    }
 }
 
-macro_rules! make_write_le(
-    ($this:expr, $n:expr, $size:expr) => ({
-          $this.write_le($n as u64, $size);
-          $this.length += $size;
-          Ok(())
-    })
-)
-
 impl Writer for SipState {
     #[inline]
-    fn write(&mut self, msg: &[u8]) -> IoResult<()> {
+    fn write(&mut self, msg: &[u8]) {
         let length = msg.len();
         self.length += length;
 
@@ -196,7 +160,7 @@ impl Writer for SipState {
             if length < needed {
                 self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail;
                 self.ntail += length;
-                return Ok(());
+                return
             }
 
             let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail;
@@ -228,60 +192,7 @@ impl Writer for SipState {
 
         self.tail = u8to64_le!(msg, i, left);
         self.ntail = left;
-
-        Ok(())
     }
-
-    #[inline]
-    fn write_u8(&mut self, n: u8) -> IoResult<()> {
-        make_write_le!(self, n, 1)
-    }
-
-    #[inline]
-    fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
-        make_write_le!(self, n, 2)
-    }
-
-    #[inline]
-    fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
-        make_write_le!(self, n, 4)
-    }
-
-    #[inline]
-    fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
-        make_write_le!(self, n, 8)
-    }
-
-    #[inline]
-    fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
-        make_write_le!(self, n, uint::BYTES)
-    }
-
-    #[inline]
-    fn write_i8(&mut self, n: i8) -> IoResult<()> {
-        make_write_le!(self, n, 1)
-    }
-
-    #[inline]
-    fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
-        make_write_le!(self, n, 2)
-    }
-
-    #[inline]
-    fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
-        make_write_le!(self, n, 4)
-    }
-
-    #[inline]
-    fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
-        make_write_le!(self, n, 8)
-    }
-
-    #[inline]
-    fn write_le_int(&mut self, n: int) -> IoResult<()> {
-        make_write_le!(self, n, int::BYTES)
-    }
-
 }
 
 impl Clone for SipState {
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index d1c75b89579..0ac26e686cd 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -14,43 +14,66 @@
 
 #![crate_id = "collections#0.11.0-pre"]
 #![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/")]
 
-#![feature(macro_rules, managed_boxes, default_type_params, phase)]
+#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
+#![no_std]
 
-#![deny(deprecated_owned_vector)]
-
-extern crate debug;
+#[phase(syntax, link)] extern crate core;
+extern crate alloc;
 
+#[cfg(test)] extern crate native;
+#[cfg(test)] extern crate std;
 #[cfg(test)] extern crate test;
 #[cfg(test)] #[phase(syntax, link)] extern crate log;
 
-pub use bitv::Bitv;
+pub use bitv::{Bitv, BitvSet};
 pub use btree::BTree;
 pub use deque::Deque;
 pub use dlist::DList;
 pub use enum_set::EnumSet;
-pub use hashmap::{HashMap, HashSet};
-pub use lru_cache::LruCache;
 pub use priority_queue::PriorityQueue;
 pub use ringbuf::RingBuf;
 pub use smallintmap::SmallIntMap;
 pub use treemap::{TreeMap, TreeSet};
 pub use trie::{TrieMap, TrieSet};
 
+mod macros;
+
 pub mod bitv;
 pub mod btree;
 pub mod deque;
 pub mod dlist;
 pub mod enum_set;
-pub mod hashmap;
-pub mod lru_cache;
 pub mod priority_queue;
 pub mod ringbuf;
 pub mod smallintmap;
 pub mod treemap;
 pub mod trie;
+pub mod slice;
+pub mod str;
+pub mod string;
+pub mod vec;
+pub mod hash;
+
+// Internal unicode fiddly bits for the str module
+mod unicode;
+
+// FIXME(#14008) should this actually exist, or should a method be added?
+fn expect<T>(a: core::option::Option<T>, b: &str) -> T {
+    match a {
+        core::option::Some(a) => a,
+        core::option::None => fail!(b),
+    }
+}
+
+mod std {
+    pub use core::fmt;      // necessary for fail!()
+    pub use core::option;   // necessary for fail!()
+    pub use core::clone;    // deriving(Clone)
+    pub use core::cmp;      // deriving(Eq, Ord, etc.)
+    pub use hash;           // deriving(Hash)
+}
diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs
new file mode 100644
index 00000000000..db062a70bbb
--- /dev/null
+++ b/src/libcollections/macros.rs
@@ -0,0 +1,22 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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.
+
+#![macro_escape]
+
+/// Create a `std::vec::Vec` containing the arguments.
+macro_rules! vec(
+    ($($e:expr),*) => ({
+        // leading _ to allow empty construction without a warning.
+        let mut _temp = ::vec::Vec::new();
+        $(_temp.push($e);)*
+        _temp
+    });
+    ($($e:expr),+,) => (vec!($($e),+))
+)
diff --git a/src/libcollections/priority_queue.rs b/src/libcollections/priority_queue.rs
index d73c07ee17d..d40051faf13 100644
--- a/src/libcollections/priority_queue.rs
+++ b/src/libcollections/priority_queue.rs
@@ -12,10 +12,12 @@
 
 #![allow(missing_doc)]
 
-use std::clone::Clone;
-use std::mem::{zeroed, replace, swap};
-use std::ptr;
-use std::slice;
+use core::prelude::*;
+
+use core::mem::{overwrite, zeroed, replace, swap};
+
+use slice;
+use vec::Vec;
 
 /// A priority queue implemented with a binary heap
 #[deriving(Clone)]
diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs
index 7b8d416c4fe..713888cf473 100644
--- a/src/libcollections/ringbuf.rs
+++ b/src/libcollections/ringbuf.rs
@@ -13,12 +13,14 @@
 //! RingBuf implements the trait Deque. It should be imported with `use
 //! collections::deque::Deque`.
 
-use std::cmp;
-use std::fmt;
-use std::fmt::Show;
-use std::iter::RandomAccessIterator;
+use core::prelude::*;
+
+use core::cmp;
+use core::fmt;
+use core::iter::RandomAccessIterator;
 
 use deque::Deque;
+use vec::Vec;
 
 static INITIAL_CAPACITY: uint = 8u; // 2^3
 static MINIMUM_CAPACITY: uint = 2u;
@@ -393,7 +395,7 @@ impl<A> Extendable<A> for RingBuf<A> {
     }
 }
 
-impl<T: Show> Show for RingBuf<T> {
+impl<T: fmt::Show> fmt::Show for RingBuf<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "["));
 
diff --git a/src/libstd/slice.rs b/src/libcollections/slice.rs
similarity index 99%
rename from src/libstd/slice.rs
rename to src/libcollections/slice.rs
index d6f63da09f2..a724307a70e 100644
--- a/src/libstd/slice.rs
+++ b/src/libcollections/slice.rs
@@ -99,20 +99,16 @@ There are a number of free functions that create or take vectors, for example:
 
 #![doc(primitive = "slice")]
 
-use mem::transmute;
-use clone::Clone;
-use cmp::{Ord, Ordering, Less, Greater};
-use cmp;
-use container::Container;
-use iter::*;
-use mem::size_of;
-use mem;
-use ops::Drop;
-use option::{None, Option, Some};
-use ptr::RawPtr;
-use ptr;
-use rt::heap::{allocate, deallocate};
-use finally::try_finally;
+use core::prelude::*;
+
+use alloc::heap::{allocate, deallocate};
+use core::cmp;
+use core::finally::try_finally;
+use core::mem::size_of;
+use core::mem::transmute;
+use core::mem;
+use core::ptr;
+use core::iter::{range_step, MultiplicativeIterator};
 use vec::Vec;
 
 pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
@@ -295,13 +291,13 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
     #[inline]
     fn to_owned(&self) -> ~[T] {
         use RawVec = core::raw::Vec;
-        use num::{CheckedAdd, CheckedMul};
+        use core::num::{CheckedAdd, CheckedMul};
 
         let len = self.len();
         let data_size = len.checked_mul(&mem::size_of::<T>());
-        let data_size = data_size.expect("overflow in to_owned()");
+        let data_size = ::expect(data_size, "overflow in to_owned()");
         let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
-        let size = size.expect("overflow in to_owned()");
+        let size = ::expect(size, "overflow in to_owned()");
 
         unsafe {
             // this should pass the real required alignment
diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs
index 932011baa56..c284a73d8bc 100644
--- a/src/libcollections/smallintmap.rs
+++ b/src/libcollections/smallintmap.rs
@@ -15,9 +15,13 @@
 
 #![allow(missing_doc)]
 
-use std::iter::{Enumerate, FilterMap};
-use std::mem::replace;
-use std::{vec, slice};
+use core::prelude::*;
+
+use core::iter::{Enumerate, FilterMap};
+use core::mem::replace;
+
+use {vec, slice};
+use vec::Vec;
 
 #[allow(missing_doc)]
 pub struct SmallIntMap<T> {
@@ -118,7 +122,7 @@ impl<V> SmallIntMap<V> {
     }
 
     pub fn get<'a>(&'a self, key: &uint) -> &'a V {
-        self.find(key).expect("key not present")
+        ::expect(self.find(key), "key not present")
     }
 
     /// An iterator visiting all key-value pairs in ascending order by the keys.
diff --git a/src/libstd/str.rs b/src/libcollections/str.rs
similarity index 98%
rename from src/libstd/str.rs
rename to src/libcollections/str.rs
index 3af3821486f..144f14acdcd 100644
--- a/src/libstd/str.rs
+++ b/src/libcollections/str.rs
@@ -67,21 +67,17 @@ is the same as `&[u8]`.
 
 #![doc(primitive = "str")]
 
-use char::Char;
-use char;
-use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Equiv, Ordering};
-use container::Container;
-use default::Default;
-use fmt;
-use io::Writer;
-use iter::{Iterator, range, AdditiveIterator};
-use mem::transmute;
-use mem;
-use option::{None, Option, Some};
-use result::Result;
-use slice::Vector;
-use slice::{ImmutableVector, MutableVector};
+use core::prelude::*;
+
+use core::char;
+use core::default::Default;
+use core::fmt;
+use core::cmp;
+use core::iter::AdditiveIterator;
+use core::mem;
+
+use hash;
+use slice::CloneableVector;
 use string::String;
 use vec::Vec;
 
@@ -201,9 +197,6 @@ Section: Iterators
 
 // Helper functions used for Unicode normalization
 fn canonical_sort(comb: &mut [(char, u8)]) {
-    use iter::range;
-    use tuple::Tuple2;
-
     let len = comb.len();
     for i in range(0, len) {
         let mut swapped = false;
@@ -638,13 +631,10 @@ impl<'a> Default for MaybeOwned<'a> {
     fn default() -> MaybeOwned<'a> { Slice("") }
 }
 
-impl<'a, H: Writer> ::hash::Hash<H> for MaybeOwned<'a> {
+impl<'a, H: hash::Writer> hash::Hash<H> for MaybeOwned<'a> {
     #[inline]
     fn hash(&self, hasher: &mut H) {
-        match *self {
-            Slice(s) => s.hash(hasher),
-            Owned(ref s) => s.as_slice().hash(hasher),
-        }
+        self.as_slice().hash(hasher)
     }
 }
 
@@ -660,10 +650,10 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
 
 /// Unsafe operations
 pub mod raw {
-    use c_str::CString;
-    use libc;
-    use mem;
-    use raw::Slice;
+    use core::prelude::*;
+    use core::mem;
+    use core::raw::Slice;
+
     use string::String;
     use vec::Vec;
 
@@ -681,9 +671,16 @@ pub mod raw {
     }
 
     /// Create a Rust string from a null-terminated C string
-    pub unsafe fn from_c_str(c_string: *libc::c_char) -> String {
+    pub unsafe fn from_c_str(c_string: *i8) -> String {
         let mut buf = String::new();
-        buf.push_bytes(CString::new(c_string, false).as_bytes_no_nul());
+        let mut len = 0;
+        while *c_string.offset(len) != 0 {
+            len += 1;
+        }
+        buf.push_bytes(mem::transmute(Slice {
+            data: c_string,
+            len: len as uint,
+        }));
         buf
     }
 
@@ -800,10 +797,8 @@ pub trait StrAllocating: Str {
     #[deprecated = "obsolete, use `to_string`"]
     #[inline]
     fn to_owned(&self) -> String {
-        use slice::Vector;
-
         unsafe {
-            ::mem::transmute(Vec::from_slice(self.as_slice().as_bytes()))
+            mem::transmute(Vec::from_slice(self.as_slice().as_bytes()))
         }
     }
 
@@ -852,9 +847,9 @@ pub trait StrAllocating: Str {
                 if sc == tc {
                     *dcol.get_mut(j + 1) = current;
                 } else {
-                    *dcol.get_mut(j + 1) = ::cmp::min(current, next);
-                    *dcol.get_mut(j + 1) = ::cmp::min(*dcol.get(j + 1),
-                                                      *dcol.get(j)) + 1;
+                    *dcol.get_mut(j + 1) = cmp::min(current, next);
+                    *dcol.get_mut(j + 1) = cmp::min(*dcol.get(j + 1),
+                                                    *dcol.get(j)) + 1;
                 }
 
                 current = next;
diff --git a/src/libstd/string.rs b/src/libcollections/string.rs
similarity index 94%
rename from src/libstd/string.rs
rename to src/libcollections/string.rs
index 80973bb5328..764811e92c7 100644
--- a/src/libstd/string.rs
+++ b/src/libcollections/string.rs
@@ -10,23 +10,17 @@
 
 //! An owned, growable string that enforces that its contents are valid UTF-8.
 
-use c_vec::CVec;
-use char::Char;
-use cmp::Equiv;
-use container::{Container, Mutable};
-use default::Default;
-use fmt;
-use from_str::FromStr;
-use io::Writer;
-use iter::{Extendable, FromIterator, Iterator, range};
-use mem;
-use option::{None, Option, Some};
-use ptr::RawPtr;
-use ptr;
-use result::{Result, Ok, Err};
-use slice::Vector;
-use str::{CharRange, Str, StrSlice, StrAllocating};
+use core::prelude::*;
+
+use core::default::Default;
+use core::fmt;
+use core::mem;
+use core::ptr;
+use core::raw::Slice;
+
+use hash;
 use str;
+use str::{CharRange, StrAllocating};
 use vec::Vec;
 
 /// A growable string stored as a UTF-8 encoded buffer.
@@ -168,14 +162,17 @@ impl String {
     #[inline]
     pub fn push_char(&mut self, ch: char) {
         let cur_len = self.len();
-        unsafe {
-            // This may use up to 4 bytes.
-            self.vec.reserve_additional(4);
+        // This may use up to 4 bytes.
+        self.vec.reserve_additional(4);
 
+        unsafe {
             // Attempt to not use an intermediate buffer by just pushing bytes
             // directly onto this string.
-            let mut c_vector = CVec::new(self.vec.as_mut_ptr().offset(cur_len as int), 4);
-            let used = ch.encode_utf8(c_vector.as_mut_slice());
+            let slice = Slice {
+                data: self.vec.as_ptr().offset(cur_len as int),
+                len: 4,
+            };
+            let used = ch.encode_utf8(mem::transmute(slice));
             self.vec.set_len(cur_len + used);
         }
     }
@@ -340,7 +337,7 @@ impl fmt::Show for String {
     }
 }
 
-impl<H:Writer> ::hash::Hash<H> for String {
+impl<H: hash::Writer> hash::Hash<H> for String {
     #[inline]
     fn hash(&self, hasher: &mut H) {
         self.as_slice().hash(hasher)
@@ -354,13 +351,6 @@ impl<'a, S: Str> Equiv<S> for String {
     }
 }
 
-impl FromStr for String {
-    #[inline]
-    fn from_str(s: &str) -> Option<String> {
-        Some(s.to_string())
-    }
-}
-
 #[cfg(test)]
 mod tests {
     extern crate test;
diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs
index 1184c9b7b52..1fd9fce2089 100644
--- a/src/libcollections/treemap.rs
+++ b/src/libcollections/treemap.rs
@@ -12,13 +12,17 @@
 //! trees. The only requirement for the types is that the key implements
 //! `Ord`.
 
-use std::cmp::Ordering;
-use std::fmt::Show;
-use std::fmt;
-use std::iter::Peekable;
-use std::iter;
-use std::mem::{replace, swap};
-use std::ptr;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::fmt;
+use core::fmt::Show;
+use core::iter::Peekable;
+use core::iter;
+use core::mem::{replace, swap};
+use core::ptr;
+
+use vec::Vec;
 
 // This is implemented as an AA tree, which is a simplified variation of
 // a red-black tree where red (horizontal) nodes can only be added
diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs
index e6df4fd87e1..a70b466623f 100644
--- a/src/libcollections/trie.rs
+++ b/src/libcollections/trie.rs
@@ -10,11 +10,15 @@
 
 //! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
 
-use std::mem::zeroed;
-use std::mem;
-use std::slice::{Items, MutItems};
-use std::slice;
-use std::uint;
+use core::prelude::*;
+
+use alloc::owned::Box;
+use core::mem::zeroed;
+use core::mem;
+use core::uint;
+
+use slice::{Items, MutItems};
+use slice;
 
 // FIXME: #5244: need to manually update the TrieNode constructor
 static SHIFT: uint = 4;
@@ -457,7 +461,7 @@ fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
             *child = Internal(new);
             return ret;
         }
-        _ => unreachable!()
+        _ => fail!("unreachable code"),
     }
 }
 
diff --git a/src/libstd/unicode.rs b/src/libcollections/unicode.rs
similarity index 98%
rename from src/libstd/unicode.rs
rename to src/libcollections/unicode.rs
index 03c960e96ff..440290164c3 100644
--- a/src/libstd/unicode.rs
+++ b/src/libcollections/unicode.rs
@@ -13,11 +13,9 @@
 #![allow(missing_doc, non_uppercase_statics)]
 
 pub mod normalization {
-    use option::{Some, None};
-    use slice::ImmutableVector;
+    use core::prelude::*;
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
-        use cmp::{Equal, Less, Greater};
         match r.bsearch(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
diff --git a/src/libstd/vec.rs b/src/libcollections/vec.rs
similarity index 97%
rename from src/libstd/vec.rs
rename to src/libcollections/vec.rs
index cdcee9464de..faa9db7c919 100644
--- a/src/libstd/vec.rs
+++ b/src/libcollections/vec.rs
@@ -10,25 +10,22 @@
 
 //! An owned, growable vector.
 
-use RawVec = raw::Vec;
-use clone::Clone;
-use cmp::{PartialOrd, PartialEq, Ordering, Eq, Ord, max};
-use container::{Container, Mutable};
-use default::Default;
-use fmt;
-use iter::{DoubleEndedIterator, FromIterator, Extendable, Iterator, range};
-use mem;
-use num::{CheckedMul, CheckedAdd};
-use num;
-use ops::{Add, Drop};
-use option::{None, Option, Some};
-use ptr::RawPtr;
-use ptr;
-use raw::Slice;
-use rt::heap::{allocate, reallocate, deallocate};
-use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
-use slice::{MutableOrdVector, OwnedVector, Vector};
-use slice::{MutableVectorAllocating};
+use core::prelude::*;
+
+use alloc::heap::{allocate, reallocate, deallocate};
+use RawVec = core::raw::Vec;
+use core::raw::Slice;
+use core::cmp::max;
+use core::default::Default;
+use core::fmt;
+use core::mem;
+use core::num::{CheckedMul, CheckedAdd};
+use core::num;
+use core::ptr;
+use core::uint;
+
+use slice::{MutableTotalOrdVector, OwnedVector, MutableVectorAllocating};
+use slice::{Items, MutItems};
 
 /// An owned, growable vector.
 ///
@@ -90,12 +87,12 @@ impl<T> Vec<T> {
     /// ```
     pub fn with_capacity(capacity: uint) -> Vec<T> {
         if mem::size_of::<T>() == 0 {
-            Vec { len: 0, cap: ::uint::MAX, ptr: 0 as *mut T }
+            Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T }
         } else if capacity == 0 {
             Vec::new()
         } else {
-            let size = capacity.checked_mul(&mem::size_of::<T>())
-                               .expect("capacity overflow");
+            let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
+                                "capacity overflow");
             let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
             Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
         }
@@ -503,8 +500,8 @@ impl<T> Vec<T> {
         if mem::size_of::<T>() == 0 { return }
 
         if capacity > self.cap {
-            let size = capacity.checked_mul(&mem::size_of::<T>())
-                               .expect("capacity overflow");
+            let size = ::expect(capacity.checked_mul(&mem::size_of::<T>()),
+                                "capacity overflow");
             unsafe {
                 self.ptr = alloc_or_realloc(self.ptr, size,
                                             self.cap * mem::size_of::<T>());
@@ -583,7 +580,7 @@ impl<T> Vec<T> {
     pub fn push(&mut self, value: T) {
         if mem::size_of::<T>() == 0 {
             // zero-size types consume no memory, so we can't rely on the address space running out
-            self.len = self.len.checked_add(&1).expect("length overflow");
+            self.len = ::expect(self.len.checked_add(&1), "length overflow");
             unsafe { mem::forget(value); }
             return
         }
@@ -1530,9 +1527,9 @@ impl<T> FromVec<T> for ~[T] {
     fn from_vec(mut v: Vec<T>) -> ~[T] {
         let len = v.len();
         let data_size = len.checked_mul(&mem::size_of::<T>());
-        let data_size = data_size.expect("overflow in from_vec()");
+        let data_size = ::expect(data_size, "overflow in from_vec()");
         let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
-        let size = size.expect("overflow in from_vec()");
+        let size = ::expect(size, "overflow in from_vec()");
 
         // In a post-DST world, we can attempt to reuse the Vec allocation by calling
         // shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
@@ -1563,7 +1560,7 @@ impl<T> FromVec<T> for ~[T] {
 /// Unsafe operations
 pub mod raw {
     use super::Vec;
-    use ptr;
+    use core::ptr;
 
     /// Constructs a vector from an unsafe pointer to a buffer.
     ///
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index f6c438698b4..eef133181e1 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -61,9 +61,7 @@
 //! types to reintroduce mutability:
 //!
 //! ```
-//! extern crate collections;
-//!
-//! use collections::HashMap;
+//! use std::collections::HashMap;
 //! use std::cell::RefCell;
 //! use std::rc::Rc;
 //!
@@ -86,8 +84,6 @@
 //! to take `&self`.
 //!
 //! ```
-//! extern crate collections;
-//!
 //! use std::cell::RefCell;
 //!
 //! struct Graph {
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index f41efdbc1db..2cce68d5f60 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -31,12 +31,6 @@ pub use self::num::radix;
 pub use self::num::Radix;
 pub use self::num::RadixFmt;
 
-macro_rules! write(
-    ($dst:expr, $($arg:tt)*) => ({
-        format_args!(|args| { $dst.write_fmt(args) }, $($arg)*)
-    })
-)
-
 mod num;
 mod float;
 pub mod rt;
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 6474c5e37a4..94901aff001 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -54,7 +54,18 @@ macro_rules! assert(
     );
 )
 
+/// Runtime assertion, only without `--cfg ndebug`
+#[macro_export]
+macro_rules! debug_assert(
+    ($(a:tt)*) => ({
+        if cfg!(not(ndebug)) {
+            assert!($($a)*);
+        }
+    })
+)
+
 /// Runtime assertion for equality, for details see std::macros
+#[macro_export]
 macro_rules! assert_eq(
     ($cond1:expr, $cond2:expr) => ({
         let c1 = $cond1;
@@ -65,6 +76,16 @@ macro_rules! assert_eq(
     })
 )
 
+/// Runtime assertion for equality, only without `--cfg ndebug`
+#[macro_export]
+macro_rules! debug_assert_eq(
+    ($($a:tt)*) => ({
+        if cfg!(not(ndebug)) {
+            assert_eq!($($a)*);
+        }
+    })
+)
+
 /// Runtime assertion, disableable at compile time
 #[macro_export]
 macro_rules! debug_assert(
@@ -86,3 +107,13 @@ macro_rules! vec( ($($e:expr),*) => ({
 
 #[cfg(test)]
 macro_rules! format( ($($arg:tt)*) => (format_args!(::fmt::format, $($arg)*)) )
+
+/// Write some formatted data into a stream.
+///
+/// Identical to the macro in `std::macros`
+#[macro_export]
+macro_rules! write(
+    ($dst:expr, $($arg:tt)*) => ({
+        format_args_method!($dst, write_fmt, $($arg)*)
+    })
+)
diff --git a/src/libcollections/hashmap.rs b/src/libstd/collections/hashmap.rs
similarity index 97%
rename from src/libcollections/hashmap.rs
rename to src/libstd/collections/hashmap.rs
index dfcb85a3e39..bcf6d139c35 100644
--- a/src/libcollections/hashmap.rs
+++ b/src/libstd/collections/hashmap.rs
@@ -10,40 +10,39 @@
 
 //! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
 
-use std::container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
-use std::clone::Clone;
-use std::cmp::{PartialEq, Eq, Equiv, max};
-use std::default::Default;
-use std::fmt;
-use std::fmt::Show;
-use std::hash::{Hash, Hasher, sip};
-use std::iter;
-use std::iter::{Iterator, FromIterator, Extendable};
-use std::iter::{FilterMap, Chain, Repeat, Zip};
-use std::iter::{range, range_inclusive};
-use std::mem::replace;
-use std::num;
-use std::option::{Option, Some, None};
-use std::rand;
-use std::rand::Rng;
-use std::result::{Ok, Err};
-use std::slice::ImmutableVector;
+use clone::Clone;
+use cmp::{max, Eq, Equiv, PartialEq};
+use container::{Container, Mutable, Set, MutableSet, Map, MutableMap};
+use default::Default;
+use fmt::Show;
+use fmt;
+use hash::{Hash, Hasher, sip};
+use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable};
+use iter::{range, range_inclusive, FromIterator};
+use iter;
+use mem::replace;
+use num;
+use option::{Some, None, Option};
+use rand::Rng;
+use rand;
+use result::{Ok, Err};
 
 mod table {
-    use std::clone::Clone;
-    use std::cmp;
-    use std::cmp::PartialEq;
-    use std::hash::{Hash, Hasher};
-    use std::kinds::marker;
-    use std::num::{CheckedMul, is_power_of_two};
-    use std::option::{Option, Some, None};
-    use std::prelude::Drop;
-    use std::ptr;
-    use std::ptr::RawPtr;
-    use std::mem::{min_align_of, size_of};
-    use std::intrinsics::{move_val_init, set_memory, transmute};
-    use std::iter::{Iterator, range_step_inclusive};
-    use std::rt::heap::{allocate, deallocate};
+    use clone::Clone;
+    use cmp;
+    use hash::{Hash, Hasher};
+    use iter::range_step_inclusive;
+    use iter::{Iterator, range};
+    use kinds::marker;
+    use mem::{min_align_of, size_of};
+    use mem::{overwrite, transmute};
+    use num::{CheckedMul, is_power_of_two};
+    use ops::Drop;
+    use option::{Some, None, Option, Expect};
+    use ptr::RawPtr;
+    use ptr::set_memory;
+    use ptr;
+    use rt::heap::{allocate, deallocate};
 
     static EMPTY_BUCKET: u64 = 0u64;
 
@@ -217,12 +216,12 @@ mod table {
         /// Does not initialize the buckets. The caller should ensure they,
         /// at the very least, set every hash to EMPTY_BUCKET.
         unsafe fn new_uninitialized(capacity: uint) -> RawTable<K, V> {
-            let hashes_size =
-                capacity.checked_mul(&size_of::<u64>()).expect("capacity overflow");
-            let keys_size   =
-                capacity.checked_mul(&size_of::< K >()).expect("capacity overflow");
-            let vals_size   =
-                capacity.checked_mul(&size_of::< V >()).expect("capacity overflow");
+            let hashes_size = capacity.checked_mul(&size_of::<u64>())
+                                      .expect("capacity overflow");
+            let keys_size = capacity.checked_mul(&size_of::< K >())
+                                    .expect("capacity overflow");
+            let vals_size = capacity.checked_mul(&size_of::< V >())
+                                    .expect("capacity overflow");
 
             // Allocating hashmaps is a little tricky. We need to allocate three
             // arrays, but since we know their sizes and alignments up front,
@@ -339,8 +338,8 @@ mod table {
             unsafe {
                 debug_assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET);
                 *self.hashes.offset(idx) = hash.inspect();
-                move_val_init(&mut *self.keys.offset(idx), k);
-                move_val_init(&mut *self.vals.offset(idx), v);
+                overwrite(&mut *self.keys.offset(idx), k);
+                overwrite(&mut *self.vals.offset(idx), v);
             }
 
             self.size += 1;
@@ -519,8 +518,8 @@ mod table {
                             let hash = idx.hash().inspect();
                             let (k, v) = self.read(&idx);
                             *new_ht.hashes.offset(i as int) = hash;
-                            move_val_init(&mut *new_ht.keys.offset(i as int), (*k).clone());
-                            move_val_init(&mut *new_ht.vals.offset(i as int), (*v).clone());
+                            overwrite(&mut *new_ht.keys.offset(i as int), (*k).clone());
+                            overwrite(&mut *new_ht.vals.offset(i as int), (*v).clone());
                         }
                     }
                 }
@@ -1037,6 +1036,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
         HashMap::with_capacity(INITIAL_CAPACITY)
     }
 
+    /// Creates an empty hash map with the given initial capacity.
     pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
         let mut r = rand::task_rng();
         let r0 = r.gen();
@@ -1047,6 +1047,9 @@ impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
 }
 
 impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
+    /// Creates an empty hashmap which will use the given hasher to hash keys.
+    ///
+    /// The creates map has the default initial capacity.
     pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
         HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
@@ -1326,7 +1329,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     pub fn get<'a>(&'a self, k: &K) -> &'a V {
         match self.find(k) {
             Some(v) => v,
-            None => fail!("No entry found for key: {:?}", k)
+            None => fail!("no entry found for key")
         }
     }
 
@@ -1334,7 +1337,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
         match self.find_mut(k) {
             Some(v) => v,
-            None => fail!("No entry found for key: {:?}", k)
+            None => fail!("no entry found for key")
         }
     }
 
@@ -1533,6 +1536,10 @@ impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
 }
 
 impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
+    /// Creates a new empty hash set which will use the given hasher to hash
+    /// keys.
+    ///
+    /// The hash set is also created with the default initial capacity.
     pub fn with_hasher(hasher: H) -> HashSet<T, H> {
         HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
@@ -1632,8 +1639,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H>
     }
 }
 
-impl<T: Eq + Hash> Default for HashSet<T, sip::SipHasher> {
-    fn default() -> HashSet<T> { HashSet::new() }
+impl<T: TotalEq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
+    fn default() -> HashSet<T, H> {
+        HashSet::with_hasher(Default::default())
+    }
 }
 
 // `Repeat` is used to feed the filter closure an explicit capture
diff --git a/src/libcollections/lru_cache.rs b/src/libstd/collections/lru_cache.rs
similarity index 97%
rename from src/libcollections/lru_cache.rs
rename to src/libstd/collections/lru_cache.rs
index ea25eee06d0..09511316a67 100644
--- a/src/libcollections/lru_cache.rs
+++ b/src/libstd/collections/lru_cache.rs
@@ -37,13 +37,18 @@
 //! assert!(cache.get(&2).is_none());
 //! ```
 
-use std::container::Container;
-use std::hash::Hash;
-use std::fmt;
-use std::mem;
-use std::ptr;
-
-use HashMap;
+use cmp::{Eq, TotalEq};
+use collections::HashMap;
+use container::{Container, Mutable, MutableMap};
+use fmt;
+use hash::Hash;
+use iter::{range, Iterator};
+use mem;
+use ops::Drop;
+use option::{Some, None, Option};
+use owned::Box;
+use ptr;
+use result::{Ok, Err};
 
 struct KeyRef<K> { k: *K }
 
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
new file mode 100644
index 00000000000..16a6a35d9d5
--- /dev/null
+++ b/src/libstd/collections/mod.rs
@@ -0,0 +1,25 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <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.
+
+/*!
+ * Collection types.
+ */
+
+pub use core_collections::{Bitv, BitvSet, BTree, Deque, DList, EnumSet};
+pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap};
+pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet};
+pub use core_collections::{bitv, btree, deque, dlist, enum_set};
+pub use core_collections::{priority_queue, ringbuf, smallintmap, treemap, trie};
+
+pub use self::hashmap::{HashMap, HashSet};
+pub use self::lru_cache::LruCache;
+
+pub mod hashmap;
+pub mod lru_cache;
diff --git a/src/libstd/from_str.rs b/src/libstd/from_str.rs
index 62bb8e4d969..4394fb9d355 100644
--- a/src/libstd/from_str.rs
+++ b/src/libstd/from_str.rs
@@ -11,6 +11,8 @@
 //! The `FromStr` trait for types that can be created from strings
 
 use option::{Option, Some, None};
+use string::String;
+use str::StrAllocating;
 
 /// A trait to abstract the idea of creating a new instance of a type from a
 /// string.
@@ -47,6 +49,13 @@ impl FromStr for bool {
     }
 }
 
+impl FromStr for String {
+    #[inline]
+    fn from_str(s: &str) -> Option<String> {
+        Some(s.to_string())
+    }
+}
+
 #[cfg(test)]
 mod test {
     use prelude::*;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index db84a724adb..90d6677d612 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -124,6 +124,7 @@ extern crate alloc;
 extern crate core;
 extern crate libc;
 extern crate core_rand = "rand";
+extern crate core_collections = "collections";
 
 // Make std testable by not duplicating lang items. See #2912
 #[cfg(test)] extern crate realstd = "std";
@@ -160,6 +161,12 @@ pub use core::option;
 pub use alloc::owned;
 pub use alloc::rc;
 
+pub use core_collections::hash;
+pub use core_collections::slice;
+pub use core_collections::str;
+pub use core_collections::string;
+pub use core_collections::vec;
+
 // Run tests with libgreen instead of libnative.
 //
 // FIXME: This egregiously hacks around starting the test runner in a different
@@ -203,10 +210,6 @@ pub mod prelude;
 #[path = "num/f32.rs"]   pub mod f32;
 #[path = "num/f64.rs"]   pub mod f64;
 
-pub mod slice;
-pub mod vec;
-pub mod str;
-pub mod string;
 pub mod rand;
 
 pub mod ascii;
@@ -218,7 +221,10 @@ pub mod gc;
 pub mod from_str;
 pub mod num;
 pub mod to_str;
-pub mod hash;
+
+/* Common data structures */
+
+pub mod collections;
 
 /* Tasks and communication */
 
@@ -242,10 +248,6 @@ pub mod cleanup;
 #[unstable]
 pub mod unstable;
 
-/* For internal use, not exported */
-
-mod unicode;
-
 // FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
 // but name resolution doesn't work without it being pub.
 #[unstable]
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index a6bbf22b401..8dfb64194e7 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -10,16 +10,17 @@
 
 //! POSIX file path handling
 
-use container::Container;
 use c_str::{CString, ToCStr};
 use clone::Clone;
 use cmp::{PartialEq, Eq};
+use container::Container;
 use from_str::FromStr;
+use hash;
 use io::Writer;
 use iter::{DoubleEndedIterator, AdditiveIterator, Extendable, Iterator, Map};
 use option::{Option, None, Some};
-use str;
 use str::Str;
+use str;
 use slice::{CloneableVector, Splits, Vector, VectorVector,
             ImmutableEqVector, OwnedVector, ImmutableVector};
 use vec::Vec;
@@ -105,7 +106,7 @@ impl<'a> ToCStr for &'a Path {
     }
 }
 
-impl<S: Writer> ::hash::Hash<S> for Path {
+impl<S: hash::Writer> hash::Hash<S> for Path {
     #[inline]
     fn hash(&self, state: &mut S) {
         self.repr.hash(state)
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 865e53cbe38..e53842ecd8f 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -16,6 +16,7 @@ use clone::Clone;
 use cmp::{PartialEq, Eq};
 use container::Container;
 use from_str::FromStr;
+use hash;
 use io::Writer;
 use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
 use mem;
@@ -126,7 +127,7 @@ impl<'a> ToCStr for &'a Path {
     }
 }
 
-impl<S: Writer> ::hash::Hash<S> for Path {
+impl<S: hash::Writer> hash::Hash<S> for Path {
     #[cfg(not(test))]
     #[inline]
     fn hash(&self, state: &mut S) {